stream: fix TypeError in writev when writer.ready rejects#62291
Open
mango766 wants to merge 1 commit intonodejs:mainfrom
Open
stream: fix TypeError in writev when writer.ready rejects#62291mango766 wants to merge 1 commit intonodejs:mainfrom
mango766 wants to merge 1 commit intonodejs:mainfrom
Conversation
The `done` callback in the `writev` handlers of both `newStreamWritableFromWritableStream` and `newStreamDuplexFromReadableWritablePair` unconditionally called `error.filter()`, assuming `error` is always an array from `SafePromiseAll`. However, `done` is also used as the rejection handler for `writer.ready`, which passes a single error value, not an array. This caused a `TypeError: error.filter is not a function` which became an unhandled rejection, crashing the process. Fix by checking whether `error` is an array before filtering, and also use `ArrayIsArray`/`ArrayPrototypeFilter` from primordials to follow Node.js internal conventions. Fixes: nodejs#62199
Renegade334
reviewed
Mar 17, 2026
Comment on lines
+785
to
+787
| // When error comes from SafePromiseAll, it is an array of | ||
| // errors (one per chunk). When it comes from writer.ready | ||
| // rejection, it is a single error. Normalize to handle both. |
Member
There was a problem hiding this comment.
I don't believe this assumption was correct originally? If an array is returned by Promise.all, then it means that all of the passed Promises resolved successfully. If any of them fail, then Promise.all will reject with the first rejection reason, not an array.
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.
The
donecallback in thewritevhandlers of bothnewStreamWritableFromWritableStreamandnewStreamDuplexFromReadableWritablePairunconditionally callederror.filter(), assumingerroris always an array (fromSafePromiseAll). However,doneis also used as the rejectionhandler for
writer.ready, which passes a single error value,not an array. This caused a
TypeError: Cannot read properties of null (reading 'filter')which became an unhandled rejection,crashing the process.
Root cause: When a
Duplex.fromWeb()stream is corked, writesare batched into a
_writevcall. Ifdestroy()is called in thesame microtask (after
uncork()), the underlyingWritableStreamwriter gets aborted, causing
writer.readyto reject. Thedonecallback then receives a single error instead of the array it
expects from
SafePromiseAll.Fix: Check whether
erroris an array before callingArrayPrototypeFilteron it. This handles both code paths:SafePromiseAllresolution/rejection → array of results/errorswriter.readyrejection → single error valueAlso uses
ArrayIsArray/ArrayPrototypeFilterfrom primordials,consistent with Node.js internal conventions.
Includes a regression test that reproduces the exact scenario from
the issue report (cork → write → write → uncork → destroy).
Fixes: #62199