denoland/deno · error · TypeError
ReadableByteStreamController's stream is not in a readable s
Error message
ReadableByteStreamController's stream is not in a readable state
What it means
Thrown by ReadableByteStreamController.close() when the controller's stream state is not "readable" (ext/web/06_streams.js), i.e. the stream is already "closed" or "errored". Once a stream has been closed by a previous close, errored via controller.error(e), or canceled by its reader, its state leaves "readable" and no further close is accepted.
Source
Thrown at ext/web/06_streams.js:6838
get byobRequest() {
webidl.assertBranded(this, ReadableByteStreamControllerPrototype);
return readableByteStreamControllerGetBYOBRequest(this);
}
/** @returns {number | null} */
get desiredSize() {
webidl.assertBranded(this, ReadableByteStreamControllerPrototype);
return readableByteStreamControllerGetDesiredSize(this);
}
/** @returns {void} */
close() {
webidl.assertBranded(this, ReadableByteStreamControllerPrototype);
if (this[_closeRequested] === true) {
throw new TypeError("Closed already requested.");
}
if (this[_stream][_state] !== "readable") {
throw new TypeError(
"ReadableByteStreamController's stream is not in a readable state",
);
}
readableByteStreamControllerClose(this);
}
/**
* @param {ArrayBufferView} chunk
* @returns {void}
*/
enqueue(chunk) {
webidl.assertBranded(this, ReadableByteStreamControllerPrototype);
const prefix =
"Failed to execute 'enqueue' on 'ReadableByteStreamController'";
webidl.requiredArguments(arguments.length, 1, prefix);
const arg1 = "Argument 1";
chunk = webidl.converters.ArrayBufferView(chunk, prefix, arg1);
let buffer, byteLength;View on GitHub (pinned to 9ad36f7a2c)
Solutions
- Pick one terminal operation per stream: either close() on success or error(e) on failure, never both.
- Before closing, check controller.desiredSize: null means errored, 0 strongly suggests already-closed; treat both as 'do not close'.
- Propagate the reader's cancel signal to your producer (implement cancel() in the underlying source) so cleanup knows not to close.
- Wrap close() in try/catch TypeError and ignore when the stream already ended.
Example fix
// before
try {
controller.enqueue(chunk);
controller.close();
} catch (e) {
controller.error(e);
controller.close(); // throws: stream is errored
}
// after
try {
controller.enqueue(chunk);
controller.close();
} catch (e) {
controller.error(e); // terminal; do not also close
} Defensive patterns
Strategy: try-catch
Validate before calling
// desiredSize: null => errored, 0 => likely closed (verify with your
// own state). Only close when the stream is provably still readable.
const ds = controller.desiredSize;
if (ds !== null && ds > 0 && !this.done) {
controller.close();
} Try / catch
try {
controller.close();
} catch (err) {
if (err instanceof TypeError && /not in a readable state/.test(err.message)) {
// stream already closed/errored/canceled — nothing to do
} else throw err;
} Prevention
- error(e) and close() are mutually exclusive terminals; call exactly one.
- Propagate reader cancellation into your source and stop closing after cancel.
- Check controller.desiredSize === null (errored) before closing defensively.
When it happens
Trigger: Calling close() after controller.error(e) in an error path; calling close() after the consumer called stream.cancel(); closing after the stream already reached "closed" state (e.g. close after close where the first close completed immediately).
Common situations: Error handling that calls error(e) and then generic cleanup calls close(); server code closing a stream after a client disconnect already canceled it; retry wrappers that close on exit while the stream ended earlier.
Related errors
- Closed already requested.
- Cannot enqueue chunk after a close has been requested
- Cannot enqueue chunk when underlying stream is not readable
- Chunk's buffer is detached and so cannot be enqueued
- "bytesWritten" must be 0 when calling respond() on a closed
AI-assisted analysis of denoland/deno@9ad36f7a2c (2026-08-20).
Data as JSON: /api/errors/3c8c00e89813ffa1.
Report an issue: GitHub.