Skip to content
FLAVIO COPES
flaviocopes.com

Astro, fix Form error “Content-Type was not one of…”

By

Fix the Astro form error 'Content-Type was not one of...' by enabling server-side rendering with output: server, or setting prerender = false on the page.

~~~

Working on a form with Astro, I got this error when submitting it:

Content-Type was not one of "multipart/form-data" or "application/x-www-form-urlencoded".

Turns out, the site was not server-side rendered, and/or the page was not hybrid.

I added output: 'server' in the Astro config in astro.config.mjs:

// @ts-check
import { defineConfig } from 'astro/config'

// https://astro.build/config
export default defineConfig({
  output: 'server'
})

I could have also added

export const prerender = false

at the top of the file that included the form (and handled form submission).

Why does this error happen?

The error comes from calling Astro.request.formData() in the page frontmatter.

formData() parses the body of the incoming request. It only works when that body is actually form data, which is what the Content-Type header declares. A browser submitting a regular HTML form sends application/x-www-form-urlencoded, or multipart/form-data if the form uploads files.

On a static (prerendered) page, there is no incoming POST request at all. The frontmatter runs once at build time, against a plain GET-like request with no form body. So formData() finds a Content-Type that’s not one of the two it accepts, and throws.

That’s why the fix is switching the page to server-side rendering. With output: 'server' (or prerender = false on that one page) the frontmatter runs on every request, including the POST the form sends.

Guard the formData() call

Even on a server-rendered page, the same error can come back.

The first time someone visits the page, the browser sends a GET request. If your frontmatter calls formData() unconditionally, it runs on that GET too, and the GET has no form body.

Check the request method before parsing:

if (Astro.request.method === 'POST') {
  const data = await Astro.request.formData()
  const email = data.get('email')
}

Also check the form itself. If you forget method="POST" on the form tag, the browser submits with GET, puts the fields in the URL, and you hit the error again:

<form method="POST">
  <input type="text" name="email" />
  <button>Subscribe</button>
</form>

One last note: output: 'server' needs an adapter (Node, Netlify, Vercel…) to deploy, since the site is no longer a folder of static files. In dev mode it works right away.

Tagged: Astro · All topics
~~~

Related posts about astro: