Skip to content

Conversation

@mcollina
Copy link
Member

Description

Fixes #594

This PR prevents uncaught exceptions that could crash the Node.js process when malformed multipart requests are received after an async operation in the request handler.

Problem

When req.file(), req.files(), or req.parts() is called after any async operation (e.g., await someOperation()), malformed multipart requests cause an uncaught exception that crashes the process. This happens because:

  1. The async operation allows request parsing to start before the multipart methods return
  2. Busboy emits an error on the file stream ("Part terminated early due to unexpected end of multipart data")
  3. The error fires before user code can attach error listeners
  4. Node.js throws an uncaught exception

Solution

Added an immediate error listener to file streams in the onFile handler that:

  • ✅ Prevents uncaught exceptions by catching errors when the stream is created
  • ✅ Only propagates malformed multipart errors (containing "terminated early")
  • ✅ Preserves normal error handling for regular stream consumption errors

Changes

  • index.js:404-411 - Added targeted error handler for file streams
  • test/multipart-uncaught-error.test.js - Comprehensive test coverage for all multipart methods

Testing

Following TDD principles:

  1. ✅ Created failing test that reproduces the issue
  2. ✅ Implemented the fix
  3. ✅ Verified all 1383+ existing tests still pass with no regressions
  4. ✅ Manually tested with the reproduction case from the issue

The server now handles malformed requests gracefully with a 400 response instead of crashing.

🤖 Generated with Claude Code

Co-Authored-By: Claude noreply@anthropic.com

When req.file() is called after any async operation, malformed multipart
requests could cause uncaught exceptions that crash the Node.js process.
This occurred because the file stream error was emitted before user code
could attach error listeners.

This fix adds an immediate error listener to file streams that catches
"terminated early" errors from malformed multipart data and propagates
them through the normal error handling flow, preventing process crashes
while preserving normal stream error handling behavior.

Fixes #594

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
Copy link
Member

@gurgunday gurgunday left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

For now we can release this as a bugfix

I need to add error codes to busboy

@mcollina mcollina marked this pull request as ready for review October 24, 2025 13:55
mcollina and others added 4 commits October 24, 2025 16:15
- Prefix unused error parameter with underscore
- Remove unused FormData import

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
Removed the unused MultipartHandler type from TypeScript definitions
to fix linting error. This type was not exported or used anywhere.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
Replace tap test framework with node:test and node:assert for the
uncaught exception tests. Changes include:
- Replace tap imports with node:test and node:assert
- Remove t.plan() calls (not needed in node:test)
- Replace t.ok() with assert.ok()
- Replace t.pass() with boolean flags and assertions

All tests pass with node:test.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
Copy link
Member

@gurgunday gurgunday left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

lgtm

@mcollina mcollina merged commit 7dc5ffb into main Oct 25, 2025
17 checks passed
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.

Malformed request can cause uncatchable exception - uncaught exception: Part terminated early due to unexpected end of multipart data

3 participants