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

  1. Never transfer or detach a buffer while a read(view) into it is pending; await the read first.
  2. Use a fresh view per read instead of a shared pool that other code may transfer.
  3. Transfer copies: after a read resolves, ship view.slice() instead of the original buffer.
  4. 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

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


AI-assisted analysis of denoland/deno@9ad36f7a2c (2026-08-20). Data as JSON: /api/errors/3e0c8c2950c31bfe. Report an issue: GitHub.