{"record":{"id":"262e788932757009","repo":"denoland/deno","slug":"cannot-enqueue-chunk-after-a-close-has-been-reques","errorCode":null,"errorMessage":"Cannot enqueue chunk after a close has been requested","messagePattern":"Cannot enqueue chunk after a close has been requested","errorType":"exception","errorClass":"TypeError","httpStatus":null,"severity":"error","filePath":"ext/web/06_streams.js","lineNumber":6885,"sourceCode":"    }\n    if (byteLength === 0) {\n      throw webidl.makeException(\n        TypeError,\n        \"Length must be non-zero\",\n        prefix,\n        arg1,\n      );\n    }\n    if (getArrayBufferByteLength(buffer) === 0) {\n      throw webidl.makeException(\n        TypeError,\n        \"Buffer length must be non-zero\",\n        prefix,\n        arg1,\n      );\n    }\n    if (this[_closeRequested] === true) {\n      throw new TypeError(\n        \"Cannot enqueue chunk after a close has been requested\",\n      );\n    }\n    if (this[_stream][_state] !== \"readable\") {\n      throw new TypeError(\n        \"Cannot enqueue chunk when underlying stream is not readable\",\n      );\n    }\n    return readableByteStreamControllerEnqueue(this, chunk);\n  }\n\n  /**\n   * @param {any=} e\n   * @returns {void}\n   */\n  error(e = undefined) {\n    webidl.assertBranded(this, ReadableByteStreamControllerPrototype);\n    if (e !== undefined) {","sourceCodeStart":6867,"sourceCodeEnd":6903,"githubUrl":"https://github.com/denoland/deno/blob/9ad36f7a2cce60488e6ec52283efb32efddaf93a/ext/web/06_streams.js#L6867-L6903","documentation":"Thrown by ReadableByteStreamController.enqueue(chunk) when this[_closeRequested] is true (ext/web/06_streams.js). After close() has been called, the stream has committed to ending and accepts no more chunks; enqueueing past that point is a producer contract violation and throws a TypeError.","triggerScenarios":"A loop or async callback calling enqueue() after the code path already called close(); an EOF branch that closes while another racing producer callback still enqueues; closing on empty source then pushing late-arriving data.","commonSituations":"Event-driven producers (file watchers, sockets) that close on idle but receive events afterwards; multiple pending pull() invocations where one closes; cleanup that closes early while buffered writes are still flushed.","solutions":["Enforce single-producer discipline: after any code path calls close(), no path may enqueue — gate both with a shared `closed`/`done` flag.","Only close when the source is fully drained; buffer late chunks and decide close vs enqueue in one place.","Check readiness before enqueueing: skip when the source signaled end or the flag says closed."],"exampleFix":"// before\nsource.on(\"end\", () => controller.close());\nsource.on(\"data\", (d) => controller.enqueue(d)); // may fire after close\n\n// after\nlet ended = false;\nsource.on(\"end\", () => { ended = true; controller.close(); });\nsource.on(\"data\", (d) => { if (!ended) controller.enqueue(d); });","handlingStrategy":"validation","validationCode":"let done = false;\nfunction push(controller, chunk) {\n  if (done) return false; // closed: stop producing\n  controller.enqueue(chunk);\n  return true;\n}\nfunction finish(controller) {\n  if (!done) { done = true; controller.close(); }\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Gate every enqueue with the same flag that close() sets.","Close only from the single EOF path; never from racing event handlers.","Buffer late-arriving chunks and drop them (or log) once done is set."],"tags":["streams","readable-stream","byte-stream","enqueue-after-close"],"backgroundTag":"stream-enqueue-after-close","analyzedSha":"9ad36f7a2cce60488e6ec52283efb32efddaf93a","analyzedAt":"2026-08-20T13:07:44.778Z","schemaVersion":2},"datasetVersion":"2026-08-31T09:17:48.483Z"}