Fix "Unexpected field" Error From 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.
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.
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 withname
and optionallymaxCount
keys - any of the above -
upload.any()
(avoid if possible)
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:
// 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:
// 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 and log the error argument. More specifically, the field
property of the error tells you which input name multer has an issue with:
// 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, you'd want to replace console.log
with a proper logging mechanism 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:
// 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:
<!-- 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:
// 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.