Fix "Unexpected field" Error From Multer
Tags: node, webdev, programming, beginners
Published: 2021-04-20 22:40:48

*This article was originally published a day earlier at https://maximorlov.com/fix-unexpected-field-error-multer/*

You set out to implement file uploads in Node.js, only to get blocked by this particular error:

`MulterError: Unexpected field`

What does this cryptic message even mean?!

By now you've already spent *several hours* trying to solve this problem. Why does implementing a simple file upload feature have to be so *hard*?!

It doesn't have to be this way though. **Writing an endpoint that accepts, parses and uploads a file in Node.js *can* be straightforward.**

After reading this article, you'll turn an annoying error into something you'll solve in less than 5 minutes!

Read on or if you prefer video, watch it below.

{% youtube 9LX3JocVO00 %}

## Input name needs to match multer function argument
The foremost cause for this error is when the *name* attribute of the file input doesn't match the argument passed to one of multer's middleware functions.

![Two code snippets: one shows an HTML form with one file input, another shows an Express POST route with a multer middleware to parse the multipart/form-data request. Both are linked with an arrow pointing at the input name in HTML, and multer argument on the server indicating they should be the same](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/trxhjnm8cbse5q7ix57p.png)

The `NAME` you use in multer's `upload.single(NAME)` middleware function (or any of the other functions discussed below) *must* be the same as  the name attribute of the input element `<input type="file" name="NAME" />`.

Therefore, you have to double-check that these values are an *exact* match. Pay extra attention to invisible whitespace or characters that may look the same but have a different Unicode value. It's better to copy-paste the value from one place to another.

Multer is strict in what input it accepts from the client, and for a good reason. File uploads can be a big vulnerability for backend servers. It's easy for a bad actor to overflow the server with a huge amount of files, or send malformed data that breaks the parser and potentially gives the hacker access to the server. Multer is designed with a mindset to trust nothing that comes from the client so it can protect your server from a potential DoS attack.

Depending on the form data you're expecting from the client, multer provides you with different middleware functions:

- no file (text only) - `upload.none()`
- single file - `upload.single(fieldname)`
- multiple files, single input - `upload.array(fieldname[, maxCount])`
- multiples files, multiple inputs - `upload.fields(fields)` where fields is an array of objects with `name` and optionally `maxCount` keys
- any of the above - `upload.any()` (avoid if possible)

>`multer.any()` is oftentimes used as a quick fix. This is dangerous and can make your server vulnerable to attacks. `multer.any()` will accept all files sent by the client which can lead to unexpected values further down in your application logic. Especially when used as a global middleware instead of a route-specific middleware.

>It's always better to fix the error by making sure field names are the same, instead of using `multer.any()`.

>If you decide to use `multer.any()`, use it only on specific routes and make sure you're handling *all* uploaded files.

Use the appropriate middleware function so that the form data received from the client is allowed to pass through. When you see an "Unexpected field" error from Multer, it's because the middleware function is rejecting some (or all) form data.

### With FormData
When you're using `FormData` to programatically construct a form, input name is the first argument to the `.append()` function:

```js
// Constructing a form in JavaScript
// Input name is the first argument of `append` function
const formData = new FormData();
formData.append('NAME', file);
```

You then have to make sure that the same value, `NAME` in this case, is used as the `fieldname` argument in the middleware function:

```js
// Pass the same input name to the multer middleware function
app.post('/upload', upload.single('NAME'), (req, res) => {
	// ...
});
```

### Inputs with multiple files might have a name ending with `[]`
In some cases, you might have a client that appends `[]` to the input name if it has multiple files.

When you configure multer to accept a `photos` field but the client sends `photos[]` instead, multer will throw a `MulterError: Unexpected field` error.

To fix the error, append `[]` to the `fieldname` argument in the middleware function: `upload.array('photos[]')`.

## Finding the unexpected field
Error messages from multer are rather cryptic. They don't give you much information to help you find the root cause of the problem.

**There's a way to extract a little bit more information from the error thrown by multer and find the rejected field.**

Add an [error handling middleware](https://expressjs.com/en/guide/error-handling.html) and log the error argument. More specifically, the `field` property of the error tells you which input name multer has an issue with:

```js
// Logging the rejected field from multer error
app.use((error, req, res, next) => {
  console.log('This is the rejected field ->', error.field);
});
```

In a [Node.js production application](https://maximorlov.com/start-node-js-in-production/), you'd want to replace `console.log` with a [proper logging mechanism](https://maximorlov.com/logging-with-pino-and-asynclocalstorage-in-nodejs/) to avoid messy logs and quickly find what you're looking for.

Having found the rejected field, you're a step closer to solving the error since you know where to start looking.

## Other possible causes
If the error persists after verifying the input name matches the multer function argument, there might be something else going on. Here are three other possible causes for this error, and a solution for each.

### Conflicting multer instances
I've seen this come up a few times so it's worth mentioning.

**Make sure there is only *one* multer instance used in the middleware chain of any particular route.**

What do I mean by this? Let's look at an example:

```js
// Typical Express application
const express = require('express');
const app = express();

app.use(upload.array());

// Some more express middleware ...

app.post('/upload', upload.single('photo'), (req, res) => {
  // ...
});
```

Can you see what's wrong with the above example?

There's a multer instance used on all routes (`upload.array()`) and another multer instance (`upload.single('photo')`) specific to the `/upload` route.

If you try to upload a single file with the correct input name (`photo`), the first multer instance will throw an error and the code never reaches the second multer instance. That's because `upload.array()` is missing a `fieldname` argument and it will always throw an error on file uploads.

If you're using multer at top of your middleware chain to get access to the authentication token in the body, you should move it to the request headers instead. It's standard practice to put an authentication token in the `Authorization` header.

### Unaccounted file inputs
Remember when I said earlier that multer is strict about accepting form data from the client?

Even if you made sure the field names are the same, you will still face this error if there are file inputs you haven't told multer about.

You can configure multer to accept multiple fields with the `upload.fields(fields)` method. `fields` is an array of objects with a `name`, and optionally `maxCount`, key.

For example, the following HTML form has two file inputs:

```html
<!-- Form with two file inputs: "avatar" and "photos" -->
<form action="/upload" method="POST" enctype="multipart/form-data">
  <input type="file" name="avatar" />
  <input type="file" name="photos" multiple />
  <input type="submit" value="Send" />
</form>
```

To configure multer to accept the above form, you would have to write the following code:

```js
// Configure multer to accept two file inputs: "avatar" and "photos".
// The "avatar" and "photos" inputs are allowed to have up to 1 and 6 files, respectively.
app.post(
  '/upload',
  upload.fields([
    { name: 'avatar', maxCount: 1 },
    { name: 'photos', maxCount: 6 },
  ]),
  (req, res) => {},
);
```

This configuration tells multer we're expecting two file input fields named "avatar" and "photos" with no more than 1 and 6 files, respectively. In case there are other fields present, multer will throw an "Unexpected field" error.

### Number of files exceeding the configured limit
When you see a `MulterError: Unexpected field` error, you don't suspect the reason to be the number of files exceeding the configured limit.

If you're using a middleware function that allows multiple files to be uploaded (`.array()` or `.fields()`), **make sure the number of files uploaded doesn't exceed the `maxCount` value.**

To quickly check if this might be the cause, set `maxCount` to a huge number (eg.: `upload.array('photos', 9999)`). If the error disappears, you've found the issue. Either increase `maxCount` to allow more files to be uploaded at once, or change the client to send fewer files at a time.

## Conclusion
Fixing cryptic multer errors and getting file uploads to work properly in Node.js can be a frustrating experience.

The foremost reason for the "Unexpected field" error is when the file input name doesn't match the argument passed to the multer function.

Other possible reasons for this error are conflicting multer instances, unaccounted file inputs and exceeding the number of files limit.

Having a hard time implementing file uploads in Node.js? Become an expert at handling file uploads with this [FREE reference guide](https://maximorlov.com/request-parsing-nodejs-guide/). Code examples, concise explanations and best practices are waiting for you.