How It Works Features Pricing Blog Error Guides
Log In Start Free Trial
Express · JavaScript

Fix MulterError: Unexpected field in Express

This error occurs when the form field name in the multipart request does not match the field name configured in multer. The middleware expects a specific field name but receives a different one. Fix it by ensuring the client form field name matches the multer configuration exactly.

Reading the Stack Trace

MulterError: Unexpected field at wrappedFileFilter (/app/node_modules/multer/lib/make-middleware.js:45:19) at Busboy.<anonymous> (/app/node_modules/multer/lib/make-middleware.js:114:7) at Busboy.emit (node:events:518:28) at Busboy._done (/app/node_modules/busboy/lib/main.js:36:33) at Busboy.<anonymous> (/app/node_modules/busboy/lib/types/multipart.js:54:15) at Multipart.<anonymous> (/app/node_modules/busboy/lib/types/multipart.js:296:14) at Multipart.emit (node:events:518:28) at HeaderParser.<anonymous> (/app/node_modules/busboy/lib/types/multipart.js:148:22) at HeaderParser.emit (node:events:518:28) at HeaderParser._finish (/app/node_modules/busboy/lib/utils.js:312:10)

Here's what each line means:

Common Causes

1. Mismatched field name between client and server

The HTML form or fetch call uses a different field name than what multer.single() or multer.fields() expects.

// Server expects 'avatar'
const upload = multer({ dest: 'uploads/' });
app.post('/upload', upload.single('avatar'), (req, res) => {
  res.json({ file: req.file });
});

// Client sends 'profileImage'
// <input type="file" name="profileImage" />

2. Using upload.single() for multiple files

The client sends multiple files but multer is configured with .single(), which only accepts one file field.

const upload = multer({ dest: 'uploads/' });

// Only accepts one file, but form sends multiple
app.post('/upload', upload.single('photo'), (req, res) => {
  res.json({ file: req.file });
});

3. No error handling for multer errors

The application does not catch MulterError, so the error propagates as an unhandled 500 instead of a descriptive 400.

const upload = multer({ dest: 'uploads/' });

app.post('/upload', upload.single('avatar'), (req, res) => {
  res.json({ file: req.file });
});
// No multer error handler

The Fix

Wrap the multer middleware call manually so you can catch MulterError and return a helpful 400 response that tells the client which field name to use. Also add a file size limit to prevent oversized uploads.

Before (broken)
const multer = require('multer');
const upload = multer({ dest: 'uploads/' });

app.post('/upload', upload.single('avatar'), (req, res) => {
  res.json({ file: req.file });
});
After (fixed)
const multer = require('multer');
const upload = multer({
  dest: 'uploads/',
  limits: { fileSize: 5 * 1024 * 1024 } // 5MB limit
});

app.post('/upload', (req, res) => {
  upload.single('avatar')(req, res, (err) => {
    if (err instanceof multer.MulterError) {
      return res.status(400).json({ error: `Upload error: ${err.message}`, field: err.field });
    }
    if (err) {
      return res.status(500).json({ error: 'Upload failed' });
    }
    if (!req.file) {
      return res.status(400).json({ error: 'No file uploaded. Use field name: avatar' });
    }
    res.json({ file: req.file });
  });
});

Testing the Fix

const request = require('supertest');
const express = require('express');
const multer = require('multer');
const path = require('path');

function createApp() {
  const app = express();
  const upload = multer({ dest: '/tmp/test-uploads/' });
  app.post('/upload', (req, res) => {
    upload.single('avatar')(req, res, (err) => {
      if (err instanceof multer.MulterError) {
        return res.status(400).json({ error: `Upload error: ${err.message}` });
      }
      if (!req.file) {
        return res.status(400).json({ error: 'No file uploaded. Use field name: avatar' });
      }
      res.json({ filename: req.file.originalname });
    });
  });
  return app;
}

describe('POST /upload', () => {
  it('returns 400 for wrong field name', async () => {
    const res = await request(createApp())
      .post('/upload')
      .attach('wrongField', Buffer.from('test'), 'test.txt');
    expect(res.status).toBe(400);
    expect(res.body.error).toContain('Upload error');
  });

  it('uploads successfully with correct field name', async () => {
    const res = await request(createApp())
      .post('/upload')
      .attach('avatar', Buffer.from('test'), 'test.txt');
    expect(res.status).toBe(200);
    expect(res.body.filename).toBe('test.txt');
  });
});

Run your tests:

npx jest --testPathPattern=multer

Pushing Through CI/CD

git checkout -b fix/express-multer-upload-error,git add src/routes/upload.js src/__tests__/multer.test.js,git commit -m "fix: handle MulterError with descriptive 400 response",git push origin fix/express-multer-upload-error

Your CI config should look something like this:

name: CI
on:
  pull_request:
    branches: [main]
jobs:
  test:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - uses: actions/setup-node@v4
        with:
          node-version: '20'
          cache: 'npm'
      - run: npm ci
      - run: npx jest --coverage
      - run: npm run lint

The Full Manual Process: 18 Steps

Here's every step you just went through to fix this one bug:

  1. Notice the error alert or see it in your monitoring tool
  2. Open the error dashboard and read the stack trace
  3. Identify the file and line number from the stack trace
  4. Open your IDE and navigate to the file
  5. Read the surrounding code to understand context
  6. Reproduce the error locally
  7. Identify the root cause
  8. Write the fix
  9. Run the test suite locally
  10. Fix any failing tests
  11. Write new tests covering the edge case
  12. Run the full test suite again
  13. Create a new git branch
  14. Commit and push your changes
  15. Open a pull request
  16. Wait for code review
  17. Merge and deploy to production
  18. Monitor production to confirm the error is resolved

Total time: 30-60 minutes. For one bug.

Or Let bugstack Fix It in Under 2 minutes

Every step above? bugstack does it automatically.

Step 1: Install the SDK

npm install bugstack-sdk

Step 2: Initialize

const { initBugStack } = require('bugstack-sdk')

initBugStack({ apiKey: process.env.BUGSTACK_API_KEY })

Step 3: There is no step 3.

bugstack handles everything from here:

  1. Captures the stack trace and request context
  2. Pulls the relevant source files from your GitHub repo
  3. Analyzes the error and understands the code context
  4. Generates a minimal, verified fix
  5. Runs your existing test suite
  6. Pushes through your CI/CD pipeline
  7. Deploys to production (or opens a PR for review)

Time from error to fix deployed: Under 2 minutes.

Human involvement: zero.

Try bugstack Free →

No credit card. 5-minute setup. Cancel anytime.

Deploying the Fix (Manual Path)

  1. Run the test suite locally to confirm multer errors return descriptive 400 responses.
  2. Open a pull request with the upload error handling changes.
  3. Wait for CI checks to pass on the PR.
  4. Have a teammate review and approve the PR.
  5. Merge to main and test file uploads in staging before promoting to production.

Frequently Asked Questions

BugStack tests uploads with correct and incorrect field names, oversized files, and missing files, then verifies proper error responses before marking it safe to deploy.

Every fix is delivered as a pull request with full CI validation. Your team reviews and approves before anything reaches production.

Yes. Use upload.fields([{ name: 'avatar', maxCount: 1 }, { name: 'gallery', maxCount: 5 }]) to accept multiple named fields with individual limits.

For production, use cloud storage (S3, GCS) via multer-s3 or similar. Memory storage works for small files you process immediately, and disk storage works for local development.