Skip to content

fix: prevent process crash when fileFilter calls its callback more than once (fixes #950)#1427

Open
spokodev wants to merge 1 commit into
expressjs:mainfrom
spokodev:fix/fields-double-callback-crash
Open

fix: prevent process crash when fileFilter calls its callback more than once (fixes #950)#1427
spokodev wants to merge 1 commit into
expressjs:mainfrom
spokodev:fix/fields-double-callback-crash

Conversation

@spokodev

@spokodev spokodev commented Jul 2, 2026

Copy link
Copy Markdown

Fixes #950.

With upload.fields(), if a fileFilter invokes its callback more than once and does so asynchronously, Multer crashes the whole Node process with an uncaught exception:

TypeError: Cannot read properties of undefined (reading 'length')
    at FileAppender.removePlaceholder (lib/file-appender.js)

A placeholder is inserted synchronously when the file event fires, then removed asynchronously from the fileFilter callback. When the callback runs twice, removePlaceholder runs twice for the same field: the first call sees length 1 and deletes req.files[fieldname]; the second call reads .length of the now-missing entry and throws on a later tick, where there is no surrounding try/catch, so the process dies. This has been reported repeatedly (#950, #1093, #1205).

Only the OBJECT strategy (upload.fields()) is affected; the ARRAY strategy (upload.array()) already tolerates a double callback because arrayRemove no-ops on a missing entry.

Fix

Break out of the OBJECT branch when the field entry is already gone, matching the null-safety the ARRAY branch already has. The single-callback path and behavior are unchanged.

Testing

Added a test to test/file-filter.js: a .fields() parser whose fileFilter calls the callback twice via setImmediate (the asynchronous case). It crashes the process on the current code and passes with the fix. Full suite stays green (81 passing).

With upload.fields(), if a fileFilter invokes its callback more than
once asynchronously, removePlaceholder runs twice for the same field:
the first call deletes req.files[fieldname], the second reads .length
of undefined and throws an uncaught TypeError that crashes the process.
Break out when the field entry is already gone, matching the array
strategy. Fixes expressjs#950.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Length is undefined in "if (this.req.files[placeholder.fieldname].length === 1)" when uploading file with invalid extension

1 participant