{"record":{"id":"3e0c8c2950c31bfe","repo":"denoland/deno","slug":"the-byob-request-s-buffer-has-been-detached-and-so","errorCode":null,"errorMessage":"The BYOB request's buffer has been detached and so cannot be filled with an enqueued chunk","messagePattern":"The BYOB request's buffer has been detached and so cannot be filled with an enqueued chunk","errorType":"exception","errorClass":"TypeError","httpStatus":null,"severity":"error","filePath":"ext/web/06_streams.js","lineNumber":1813,"sourceCode":"    byteLength = DataViewPrototypeGetByteLength(\n      /** @type {DataView} */ (chunk),\n    );\n    byteOffset = DataViewPrototypeGetByteOffset(\n      /** @type {DataView} */ (chunk),\n    );\n  }\n\n  if (isDetachedBuffer(buffer)) {\n    throw new TypeError(\n      \"Chunk's buffer is detached and so cannot be enqueued\",\n    );\n  }\n  const transferredBuffer = ArrayBufferPrototypeTransferToFixedLength(buffer);\n  if (controller[_pendingPullIntos].size !== 0) {\n    const firstPendingPullInto = controller[_pendingPullIntos].peek();\n    // deno-lint-ignore deno-internal/prefer-primordials\n    if (isDetachedBuffer(firstPendingPullInto.buffer)) {\n      throw new TypeError(\n        \"The BYOB request's buffer has been detached and so cannot be filled with an enqueued chunk\",\n      );\n    }\n    readableByteStreamControllerInvalidateBYOBRequest(controller);\n    firstPendingPullInto.buffer = ArrayBufferPrototypeTransferToFixedLength(\n      // deno-lint-ignore deno-internal/prefer-primordials\n      firstPendingPullInto.buffer,\n    );\n    if (firstPendingPullInto.readerType === \"none\") {\n      readableByteStreamControllerEnqueueDetachedPullIntoToQueue(\n        controller,\n        firstPendingPullInto,\n      );\n    }\n  }\n  if (readableStreamHasDefaultReader(stream)) {\n    readableByteStreamControllerProcessReadRequestsUsingQueue(controller);\n    if (readableStreamGetNumReadRequests(stream) === 0) {","sourceCodeStart":1795,"sourceCodeEnd":1831,"githubUrl":"https://github.com/denoland/deno/blob/9ad36f7a2cce60488e6ec52283efb32efddaf93a/ext/web/06_streams.js#L1795-L1831","documentation":"Thrown by ReadableByteStreamController.enqueue() when the byte stream has pending BYOB pull-into descriptors (an outstanding reader.read(view) from getReader({ mode: 'byob' })) and the first pending descriptor's buffer has been detached. The controller cannot transfer enqueued bytes into a consumer buffer that no longer owns its memory, so the enqueue is refused.","triggerScenarios":"reader.read(view) is pending and, before the producer enqueues, code detaches view's buffer via transfer() or a postMessage transfer list; the same pooled buffer is handed to another transferring API while the BYOB read is unresolved.","commonSituations":"Zero-copy pipelines where the BYOB read buffer is also shipped to a Worker; reusing one pooled buffer across concurrent reads and transfers; growable ArrayBuffers resized (which detaches them) mid-read.","solutions":["Never transfer or detach a buffer while a read(view) into it is pending; await the read first.","Use a fresh view per read instead of a shared pool that other code may transfer.","Transfer copies: after a read resolves, ship view.slice() instead of the original buffer.","Audit every postMessage(x, [x]) / transfer() call that can reach a buffer used for BYOB reads."],"exampleFix":"// before\nconst pending = reader.read(pooledView);\nworker.postMessage(pooledView.buffer, [pooledView.buffer]); // detaches the pending BYOB buffer\ncontroller.enqueue(data); // TypeError: The BYOB request's buffer has been detached\n\n// after\nconst { value } = await reader.read(pooledView);\nconst copy = value.slice();\nworker.postMessage(copy, [copy.buffer]); // transfer only the copy\ncontroller.enqueue(data);                // pending buffer intact","handlingStrategy":"validation","validationCode":"// inside pull()/before enqueue on a byte stream with BYOB consumers\nconst req = controller.byobRequest;\nif (req !== null && req.view.buffer.detached === true) {\n  // consumer destroyed its read buffer; surface the error instead of enqueueing\n  controller.error(new TypeError('BYOB consumer buffer detached'));\n  return;\n}\ncontroller.enqueue(data);","typeGuard":null,"tryCatchPattern":"try {\n  controller.enqueue(data);\n} catch (e) {\n  if (e instanceof TypeError && e.message.includes(\"BYOB request's buffer\")) {\n    controller.error(e); // the consumer's buffer cannot be recovered\n  }\n  throw e;\n}","preventionTips":["A view handed to read(view) belongs to that read until its promise settles.","Ship copies (view.slice()) onward in zero-copy pipelines; never the live read buffer.","Never resize growable buffers while a BYOB read is pending."],"tags":["readable-stream","byob-reader","arraybuffer","detached-buffer","enqueue"],"backgroundTag":"detached-arraybuffer","analyzedSha":"9ad36f7a2cce60488e6ec52283efb32efddaf93a","analyzedAt":"2026-08-20T13:07:44.778Z","schemaVersion":2},"datasetVersion":"2026-08-31T04:17:50.494Z"}