Repository navigation
Duplex.fromWeb leads to rare internal unhandled rejection #62199
Description
Version
v22.22.0
Platform
ubuntu-24.04 (GitHub Actions runner) 20260302.42.1
Subsystem
webstreams
What steps will reproduce the bug?
I encountered this as an occasional flake during CI runs, and haven't been able to narrow down the precise sequence of events which cause it, but the root cause in the Node.js code is clear, and suggests an approximate sequence of events (but with some unknown timing requirements):
import { TransformStream } from 'node:stream/web';
import { Duplex } from 'node:stream';
const output = Duplex.fromWeb(new TransformStream());
output.destroy();
output.write('test');Specifically, it requires the outer error path in this block (line 729) to be invoked:
node/lib/internal/webstreams/adapters.js
Lines 719 to 730 in bb73c10
| PromisePrototypeThen( | |
| writer.ready, | |
| () => { | |
| return PromisePrototypeThen( | |
| SafePromiseAll( | |
| chunks, | |
| (data) => writer.write(data.chunk)), | |
| done, | |
| done); | |
| }, | |
| done); | |
| }, |
Though this was observed in Node.js 22.22.0 (and 20.20.0), the same code still exists in the latest version:
node/lib/internal/webstreams/adapters.js
Lines 791 to 802 in 9ff27fd
| PromisePrototypeThen( | |
| writer.ready, | |
| () => { | |
| return PromisePrototypeThen( | |
| SafePromiseAll( | |
| chunks, | |
| (data) => writer.write(data.chunk)), | |
| done, | |
| done); | |
| }, | |
| done); | |
| }, |
How often does it reproduce? Is there a required condition?
Intermittently reproduces. Presumably a small race window which causes this specific error path.
What is the expected behavior? Why is that the expected behavior?
The error handler expects to receive an array (which it will, if the error comes from SafePromiseAll), which it can filter. It then uses process.nextTick explicitly to prevent unhandled rejections. This suggests that the code is intended to never result in an unhandled rejection which would kill the process.
What do you see instead?
Process terminates due to an unhandled rejection:
node:internal/webstreams/adapters:706
error = error.filter((e) => e);
^
TypeError: Cannot read properties of null (reading 'filter')
at done (node:internal/webstreams/adapters:706:23)
Additional information
The same pattern (and presumably the same bug) also exists in newStreamWritableFromWritableStream.
Activity
davidje13 commentedon Mar 11, 2026
I have managed to make a reliable reproduction. This fails every time:
By
corking, we force the_writevcodepath, which is the broken one (_writedoes not have the same issue), and bydestroying the stream in the same microtask (but after calling_writevviauncork), we trigger the unhandled rejection.Stop using Duplex.fromWeb(new TransformStream()) in tests to avoid no…
stream: fix TypeError in writev when writer.ready rejects
khalidsaidi commentedon Mar 25, 2026
stream: fix writev unhandled rejection in fromWeb
stream: fix writev unhandled rejection in fromWeb
stream: fix writev unhandled rejection in fromWeb
stream: fix writev unhandled rejection in fromWeb
stream: fix writev unhandled rejection in fromWeb