Common Errors: FormData multipart fetch issues

Join the AI Workshop to learn more about AI and how it can be applied to web development. Next cohort February 1st, 2026

The AI-first Web Development BOOTCAMP cohort starts February 24th, 2026. 10 weeks of intensive training and hands-on projects.


When uploading files using the Fetch API with FormData, you might encounter issues where the file data isn’t actually sent to the server.

The problem

Here’s a typical setup that might fail:

<form
  encType='multipart/form-data'
  action='/api/post'
  method='POST'
  onSubmit={async (e) => {
    e.preventDefault()

    const body = new FormData()
    body.append('image', image)
    body.append('title', title)
    body.append('content', content)

    const res = await fetch('/api/post', {
      body,
      method: 'POST',
      headers: {
        'Content-Type': 'multipart/form-data',
      },
    })
  }}
>
...
</form>

The file data isn’t being sent to the server correctly.

The solution

Do NOT set the Content-Type header manually.

Remove the headers from the fetch request:

const res = await fetch('/api/post', {
  body,
  method: 'POST',
  // No headers!
})

Why this works

When you use FormData, the browser needs to:

  1. Set the Content-Type to multipart/form-data
  2. Add a boundary parameter that separates the different parts of the form data

When you manually set Content-Type: 'multipart/form-data', you’re overriding the browser’s header without the boundary. The server then can’t parse the data correctly.

By omitting the header, the browser automatically sets:

Content-Type: multipart/form-data; boundary=----WebKitFormBoundary...

Correct example

const handleSubmit = async (e) => {
  e.preventDefault()

  const formData = new FormData()
  formData.append('image', imageFile)
  formData.append('title', title)
  formData.append('content', content)

  const response = await fetch('/api/upload', {
    method: 'POST',
    body: formData,
    // Let the browser set the Content-Type header automatically
  })

  const result = await response.json()
}

Key takeaway

When using FormData with fetch, let the browser handle the Content-Type header. This applies to any situation where you’re sending files or multipart data.

Lessons in this unit:

0: Introduction
1: "X is not a function" errors
2: "document is not defined" error
3: Cannot assign to read only property
4: Parse failure: Unterminated string constant
5: ▶︎ FormData multipart fetch issues
6: regeneratorRuntime is not defined
7: Unexpected identifier in modules
8: Unterminated string literal