Commit b8090ca4f6b for nodejs
commit b8090ca4f6b966da81eef7705af91c1f84e5b351
Author: James M Snell <jasnell@gmail.com>
Date: Sat Oct 3 15:10:07 2026 +0000
stream: reject closed fromWritable() writes with a TypeError
The spec (Writer write(), step 2) requires writes to a closed writer to
reject with a TypeError. The fromWritable() adapter rejected write()
and writev() with ERR_STREAM_WRITE_AFTER_END, which is a plain Error,
unlike the other stream/iter writers.
Add a TypeError variant of ERR_STREAM_WRITE_AFTER_END and use it, so
the error code is unchanged.
Assisted-by: OpenCode
Signed-off-by: James M Snell <jasnell@gmail.com>
PR-URL: https://github.com/nodejs/node/pull/66483
Reviewed-By: Trivikram Kamat <trivikr.dev@gmail.com>
diff --git a/lib/internal/errors.js b/lib/internal/errors.js
index 0e80f682817..ddd07a98209 100644
--- a/lib/internal/errors.js
+++ b/lib/internal/errors.js
@@ -1848,7 +1848,7 @@ E('ERR_STREAM_UNABLE_TO_PIPE', 'Cannot pipe to a closed or destroyed stream', Er
E('ERR_STREAM_UNSHIFT_AFTER_END_EVENT',
'stream.unshift() after end event', Error);
E('ERR_STREAM_WRAP', 'Stream has StringDecoder set or is in objectMode', Error);
-E('ERR_STREAM_WRITE_AFTER_END', 'write after end', Error);
+E('ERR_STREAM_WRITE_AFTER_END', 'write after end', Error, TypeError);
E('ERR_SYNTHETIC', 'JavaScript Callstack', Error);
E('ERR_SYSTEM_ERROR', 'A system error occurred', SystemError, HideStackFramesError);
E('ERR_TEST_FAILURE', function(error, failureType) {
diff --git a/lib/internal/streams/iter/classic.js b/lib/internal/streams/iter/classic.js
index 59eb5be5819..2c1fa640714 100644
--- a/lib/internal/streams/iter/classic.js
+++ b/lib/internal/streams/iter/classic.js
@@ -912,7 +912,7 @@ function fromWritable(writable, options = kNullPrototype) {
syncWritableError();
if (errored) return PromiseReject(error);
if (!isWritable()) {
- return PromiseReject(new ERR_STREAM_WRITE_AFTER_END());
+ return PromiseReject(new ERR_STREAM_WRITE_AFTER_END.TypeError());
}
if (signal?.aborted) return PromiseReject(signal.reason);
@@ -944,7 +944,7 @@ function fromWritable(writable, options = kNullPrototype) {
syncWritableError();
if (errored) return PromiseReject(error);
if (!isWritable()) {
- return PromiseReject(new ERR_STREAM_WRITE_AFTER_END());
+ return PromiseReject(new ERR_STREAM_WRITE_AFTER_END.TypeError());
}
if (signal?.aborted) return PromiseReject(signal.reason);
if (chunks.length === 0) return PromiseResolve();
diff --git a/test/parallel/test-stream-iter-from-writable-lifecycle.js b/test/parallel/test-stream-iter-from-writable-lifecycle.js
index cf6732c4184..d5be23fdd03 100644
--- a/test/parallel/test-stream-iter-from-writable-lifecycle.js
+++ b/test/parallel/test-stream-iter-from-writable-lifecycle.js
@@ -202,7 +202,7 @@ async function testAlreadyFinished() {
const writer = fromWritable(writable);
assert.strictEqual(writer.canWrite, null);
await assert.rejects(writer.write('a'),
- { code: 'ERR_STREAM_WRITE_AFTER_END' });
+ { code: 'ERR_STREAM_WRITE_AFTER_END', name: 'TypeError' });
assert.strictEqual(await writer.end(), 0);
assertNoTerminalListeners(writable);
}
@@ -215,7 +215,7 @@ async function testAlreadyDestroyed() {
const writer = fromWritable(writable);
assert.strictEqual(writer.canWrite, null);
await assert.rejects(writer.write('a'),
- { code: 'ERR_STREAM_WRITE_AFTER_END' });
+ { code: 'ERR_STREAM_WRITE_AFTER_END', name: 'TypeError' });
assertNoTerminalListeners(writable);
}
diff --git a/test/parallel/test-stream-iter-writable-interop.js b/test/parallel/test-stream-iter-writable-interop.js
index af2e05aae94..f00aae92425 100644
--- a/test/parallel/test-stream-iter-writable-interop.js
+++ b/test/parallel/test-stream-iter-writable-interop.js
@@ -718,7 +718,7 @@ async function testWriteAfterEnd() {
await assert.rejects(
writer.write('should fail'),
- { code: 'ERR_STREAM_WRITE_AFTER_END' },
+ { code: 'ERR_STREAM_WRITE_AFTER_END', name: 'TypeError' },
);
}