{"record":{"id":"06f2750df8f4cbdd","repo":"denoland/deno","slug":"readable-stream-is-unavailable","errorCode":null,"errorMessage":"Readable stream is unavailable","messagePattern":"Readable stream is unavailable","errorType":"exception","errorClass":"TypeError","httpStatus":null,"severity":"error","filePath":"ext/web/06_streams.js","lineNumber":4848,"sourceCode":"  controller[_transformAlgorithm] = undefined;\n  controller[_flushAlgorithm] = undefined;\n  controller[_cancelAlgorithm] = undefined;\n}\n\n/**\n * @template O\n * @param {TransformStreamDefaultController<O>} controller\n * @param {O} chunk\n */\nfunction transformStreamDefaultControllerEnqueue(controller, chunk) {\n  const stream = controller[_stream];\n  const readableController = stream[_readable][_controller];\n  if (\n    readableStreamDefaultControllerCanCloseOrEnqueue(\n      /** @type {ReadableStreamDefaultController<O>} */ readableController,\n    ) === false\n  ) {\n    throw new TypeError(\"Readable stream is unavailable\");\n  }\n  try {\n    readableStreamDefaultControllerEnqueue(\n      /** @type {ReadableStreamDefaultController<O>} */ readableController,\n      chunk,\n    );\n  } catch (e) {\n    transformStreamErrorWritableAndUnblockWrite(stream, e);\n    throw stream[_readable][_storedError];\n  }\n  const backpressure = readableStreamDefaultcontrollerHasBackpressure(\n    /** @type {ReadableStreamDefaultController<O>} */ readableController,\n  );\n  if (backpressure !== stream[_backpressure]) {\n    assert(backpressure === true);\n    transformStreamSetBackpressure(stream, true);\n  }\n}","sourceCodeStart":4830,"sourceCodeEnd":4866,"githubUrl":"https://github.com/denoland/deno/blob/9ad36f7a2cce60488e6ec52283efb32efddaf93a/ext/web/06_streams.js#L4830-L4866","documentation":"TransformStreamDefaultController.enqueue() was called while the TransformStream's readable side can no longer accept chunks — it is closed or errored, so readableStreamDefaultControllerCanCloseOrEnqueue is false. Typical causes: the consumer cancelled the readable side, a previous transform already called controller.close() or controller.error(), or enqueue runs after the stream finished.","triggerScenarios":"controller.enqueue(chunk) after controller.close() in the same transformer; enqueueing after controller.error(...) or after an earlier enqueue threw; async work started in transform() resolving after the consumer cancelled the readable side.","commonSituations":"Transformers emitting a final chunk from flush() after closing early; fire-and-forget promises inside transform(); multi-stage pipelines where a downstream stage errored or the client disconnected.","solutions":["Check controller.desiredSize — it is null exactly when the readable side is closed or errored; skip the enqueue then.","Do not enqueue after close() or error(); make flush() a no-op once the readable side is gone.","Treat downstream cancellation as a stop signal: abort outstanding work instead of continuing to transform."],"exampleFix":"// before\ntransform(chunk, controller) {\n  controller.close();\n  controller.enqueue(chunk); // readable closed -> TypeError\n}\n\n// after\ntransform(chunk, controller) {\n  if (controller.desiredSize === null) return; // readable gone\n  controller.enqueue(chunk);\n}","handlingStrategy":"validation","validationCode":"// inside transform()/flush()\nif (controller.desiredSize === null) {\n  return; // readable side closed or errored — do not enqueue\n}\ncontroller.enqueue(out);","typeGuard":null,"tryCatchPattern":"try {\n  controller.enqueue(out);\n} catch (e) {\n  if (e instanceof TypeError && e.message === 'Readable stream is unavailable') {\n    return; // consumer is gone: stop transforming, let cancellation propagate\n  }\n  throw e;\n}","preventionTips":["desiredSize === null is the canonical 'cannot enqueue' signal on transform controllers.","Never enqueue after close() or error().","Treat downstream cancellation as a stop signal for upstream work."],"tags":["transform-stream","enqueue","stream-state","cancelled"],"backgroundTag":"transform-stream-readable-unavailable","analyzedSha":"9ad36f7a2cce60488e6ec52283efb32efddaf93a","analyzedAt":"2026-08-20T13:07:44.778Z","contentChangedAt":"2026-08-20T13:07:44.778Z","schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}