NextJS + Netlify Forms 404 Errors

Hi all,

I’m having difficulty getting the contact page on my NextJS website to work with Netlify Forms. I’ve been chatting back and forth with Ask Netlify but we haven’t managed to find a solution.

My scenario is simple: I have a NextJS client component (marked with "use client" at the top of the file) which is rendering a form. Therefore, I understand since this is a JavaScript-rendered form + it’s rendered on the client-side, Netlify won’t be able to detect it at build time. In fact I was originally getting a build error like this.

1:37:44 PM:   Error message
1:37:44 PM:   Error: Failed assembling prerendered content for upload
1:37:44 PM:   @netlify/plugin-nextjs@5 requires migration steps to support Netlify Forms. Refer to https://ntl.fyi/next-runtime-forms-migration for migration example.

From that error message it became pretty clear that Netlify Forms is designed to work with forms as static HTML. However, this website: Using Netlify Forms with Next.js - OpenNext which is linked to in the Netlify documentation, promises a workaround for NextJS projects which I should be able to implement.

I followed the steps to the letter. I made a __forms.html file containing the hidden HTML form within my /public directory.

Step 3 says "In your dynamic page or form component, handle the submission by serving a POST request to the static HTML file you’ve created above (using the example above: /__forms)."

Fine. I coded a POST request to /__forms.html. But no matter what, it fails with a 404. GET requests work well and return the form HTML, so that confirms I’m not trying to perform a fetch request using an invalid file path. The file indeed exists, but seems that it is not allowing POST requests, resulting in 404 responses.

Simultaneously, it’s important to note there does NOT seem to be any issue with Netlify’s form processing. On the backend, it is detecting my form (thanks to __forms.html in /public. If I remove this, it fails to detect the form). Furthermore, if in the browser I manually navigate to https://quentinfalzon.netlify.app/__forms.html, unhide the form from the inspector and submit the form, Netlify records this as a form submission.

So to summarize, I need to programmatically trigger a submission of the form in /public/__forms.html. I need help with the POST request. It seems like I must be missing some step/detail, or the method outlined in the OpenNext article no longer is correct (or wasn’t correct to begin with?). Quoting step 3 again, “serving a POST request to the static HTML file” does not seem to be allowed.

Also - side question: What’s the point of placing validation on the JS-rendered form if ultimately a bad actor can perform an arbitrary number of form submissions by accessing the static form page within /public, unhiding it and submitting? I’m hoping there are no malicious users on these forums.

Thank you in advance everyone,
Kind regards,
Quentin

@sir_sauce Have you enabled form detection for the site?

Hi @nathanmartin, thanks for your reply.

Yes I have absolutely enabled form detection for the site. The form is working and accepting submissions. I managed to test this by navigating to <my-website-url>/__forms.html, unhiding the HTML form and clicking the submit button manually. Consequently it shows up on Netlify’s backend as a valid submission.

What I am struggling with is submitting the form programmatically. Sending a POST request to the form is returning a 404 response. Please see the attached image.

Trying to submit the form on your website does nothing currently. Has something changed?

Hi @hrishikesh,

Nothing has changed - if you open the inspector and go to the network tab you should see the form is failing with a 404 response, as I showed in my screenshot in the last reply.

I don’t, which is why I’m asking. Clicking the button does nothing and if I select the form element and use $0.submit() in the console, it just refreshes the page indicating there’s no JavaScript submission event associated with the form.

To clarify please - which form are you trying to submit? The visible form at Quentin Falzon? Or the hidden one at https://quentinfalzon.netlify.app/__forms.html?

EDIT: It could be that the form is not doing anything because my JavaScript validation is preventing submission. The name field must not be longer than 80 characters, the email field must take the form a@b and the message field needs to be between 100 and 5000 characters long.

@sir_sauce @hrishikesh I’ve determined why you’re seeing different things.

The form appears to require the message to be beyond a certain length before it attempts to submit.

Prior to that it will just set the focus to the message field but not actually show an error.

This gives the impression that the form does not work.


@sir_sauce The form submission isn’t working because it’s not sending a value for form-name

This is mentioned in the documentation here:

It should also be in the documentation you referenced relating to Next.

@nathanmartin thank you for that observation! It is confirmed to be working now. The issue was that I was not providing a form-name value, as you said. I should have thought to compare the body of the working “static” form and that of my broken JSX form. From there I would have noticed that the former includes a form-name value and the latter does not!

As far I understood from the documentation, it is required to include a snippet like this in my JSX form, which I did from the very beginning: (code below is pasted from my JSX!)

      {/* Hidden input link required by Netlify. */}
      <input type="hidden" name="form-name" value="contact" />

A bit further down in the Netlify documentation page, it states that:

“If you haven’t added a hidden form-name input to your JavaScript-rendered form, you need to send a form-name attribute in the AJAX POST request body.”

This is where I unknowingly faltered. Since I had added a hidden form-name input, I stuck to the documentation and did not send a form-name field in the AJAX POST request body!

Ultimately I think my issue occured because of the validation library I’m using (react hook form). Even though I had included a hidden input in my JSX, it was not being included in the form submission. I had something like this:

type ContactFormData = {
  name: string
  email: string
  message: string
}

...

async function onSubmit(formData: ContactFormData) {

  const requestOptions = {
    method: "POST",
    headers: { "Content-Type": "application/x-www-form-urlencoded" },
    body: new URLSearchParams(formData).toString(),
    // body only contains name, email & message. No form-name!
  }

  // Guaranteed 404 due to missing form-name attribute in body!
  const response = await fetch("/__forms.html", requestOptions)
}

Seems like the examples in the documentation use FormData(), which likely behaves differently, in the sense that it would include form-name I’m guessing.

TL;DR
It would be great if the Netlify documentation and OpenNext documentation emphasized more that for a Netlify form to work, it MUST receive the form-name field in the POST request body. And simply including a hidden input with this form-name + value might not always achieve this.

It does as long as you use new FormData(formElement) in your JavaScript code and send that as the body.