fix: error the body stream when a FormData Blob part fails to read - #5836
Open
ethanstoner wants to merge 1 commit into
Open
ethanstoner wants to merge 1 commit into
ethanstoner wants to merge 1 commit into
Conversation
extractBody's async IIFE for FormData/string/BufferSource bodies (added in nodejs#4791) ran `for await` over the action's async iterator with no try/catch. When a FormData part is a Blob whose stream() throws (e.g. a file-backed Blob from fs.openAsBlob() whose underlying file changed after being read), the throw propagated out of the un-awaited IIFE and became an unhandled promise rejection instead of erroring the body's ReadableStream. This crashed the process instead of causing the fetch or body read to reject, and regressed behavior present before nodejs#4791, where pull() returned iterator.next() and a rejection there errored the stream naturally. Wrap the IIFE body in try/catch and call controller.error(err) on failure so the stream errors and any pending read (e.g. response.text()) rejects instead. Fixes nodejs#5835 Co-Authored-By: Claude <noreply@anthropic.com>
Codecov Report✅ All modified and coverable lines are covered by tests. Additional details and impacted files@@ Coverage Diff @@
## main #5836 +/- ##
=======================================
Coverage 93.53% 93.53%
=======================================
Files 110 110
Lines 39773 39779 +6
=======================================
+ Hits 37200 37206 +6
Misses 2573 2573 ☔ View full report in Codecov by Harness. 🚀 New features to boost your workflow:
|
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Fixes #5835.
If a FormData body contains a Blob whose stream fails partway through (for
example a file from
fs.openAsBlob()that changed after it was opened), theprocess crashes with an unhandled rejection. Anything reading the body never
gets an error back.
Since #4791,
extractBodywrites the multipart parts from an async functionthat nothing awaits, with no try/catch. When a part's stream throws, the error
escapes as an unhandled rejection and the ReadableStream is never errored.
Before #4791,
pull()returnediterator.next(), so the same failure erroredthe stream.
This wraps that loop in a try/catch and calls
controller.error(err)onfailure.
response.text()now rejects withNotReadableError.Testing:
test/fetch/issue-5835.js: fails on main with an unhandled rejection,passes with the fix.
fetch()uploading the broken Blob rejects with a TypeError caused by
NotReadableError, and that cancelling the body partway through leaves no
unhandled rejection.
test/fetchpasses apart from tests that fail the same way on main.npm run lintis clean.I used Claude Code to find the cause and write the fix and test. I reviewed the
change, ran the checks above, and can answer questions about it.