denoland/deno · error · TypeError
The BYOB request's buffer has been detached and so cannot be
Error message
The BYOB request's buffer has been detached and so cannot be filled with an enqueued chunk
What it means
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.
Source
Thrown at ext/web/06_streams.js:1813
byteLength = DataViewPrototypeGetByteLength(
/** @type {DataView} */ (chunk),
);
byteOffset = DataViewPrototypeGetByteOffset(
/** @type {DataView} */ (chunk),
);
}
if (isDetachedBuffer(buffer)) {
throw new TypeError(
"Chunk's buffer is detached and so cannot be enqueued",
);
}
const transferredBuffer = ArrayBufferPrototypeTransferToFixedLength(buffer);
if (controller[_pendingPullIntos].size !== 0) {
const firstPendingPullInto = controller[_pendingPullIntos].peek();
// deno-lint-ignore deno-internal/prefer-primordials
if (isDetachedBuffer(firstPendingPullInto.buffer)) {
throw new TypeError(
"The BYOB request's buffer has been detached and so cannot be filled with an enqueued chunk",
);
}
readableByteStreamControllerInvalidateBYOBRequest(controller);
firstPendingPullInto.buffer = ArrayBufferPrototypeTransferToFixedLength(
// deno-lint-ignore deno-internal/prefer-primordials
firstPendingPullInto.buffer,
);
if (firstPendingPullInto.readerType === "none") {
readableByteStreamControllerEnqueueDetachedPullIntoToQueue(
controller,
firstPendingPullInto,
);
}
}
if (readableStreamHasDefaultReader(stream)) {
readableByteStreamControllerProcessReadRequestsUsingQueue(controller);
if (readableStreamGetNumReadRequests(stream) === 0) {View on GitHub (pinned to 9ad36f7a2c)
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.
Example fix
// before
const pending = reader.read(pooledView);
worker.postMessage(pooledView.buffer, [pooledView.buffer]); // detaches the pending BYOB buffer
controller.enqueue(data); // TypeError: The BYOB request's buffer has been detached
// after
const { value } = await reader.read(pooledView);
const copy = value.slice();
worker.postMessage(copy, [copy.buffer]); // transfer only the copy
controller.enqueue(data); // pending buffer intact Defensive patterns
Strategy: validation
Validate before calling
// inside pull()/before enqueue on a byte stream with BYOB consumers
const req = controller.byobRequest;
if (req !== null && req.view.buffer.detached === true) {
// consumer destroyed its read buffer; surface the error instead of enqueueing
controller.error(new TypeError('BYOB consumer buffer detached'));
return;
}
controller.enqueue(data); Try / catch
try {
controller.enqueue(data);
} catch (e) {
if (e instanceof TypeError && e.message.includes("BYOB request's buffer")) {
controller.error(e); // the consumer's buffer cannot be recovered
}
throw e;
} Prevention
- 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.
When it happens
Trigger: 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.
Common situations: 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.
Related errors
- Chunk's buffer is detached and so cannot be enqueued
- The buffer of view has different capacity than byobRequest
- The BYOB request's buffer has been detached and so cannot be
- "bytesWritten" must be 0 when calling respond() on a closed
- "bytesWritten" must be greater than 0 when calling respond()
AI-assisted analysis of denoland/deno@9ad36f7a2c (2026-08-20).
Data as JSON: /api/errors/3e0c8c2950c31bfe.
Report an issue: GitHub.