denoland/deno · error · TypeError

The given view's buffer has been detached and so cannot be u

Error message

The given view's buffer has been detached and so cannot be used as a response

What it means

Thrown by ReadableStreamBYOBRequest.respondWithNewView(view) when the passed-in view's buffer is detached (ext/web/06_streams.js). The method extracts the view's underlying ArrayBuffer (for typed arrays via TypedArrayPrototypeGetBuffer, for DataView via its buffer) and rejects it with isDetachedBuffer, because a detached buffer has no backing memory to receive the response bytes.

Source

Thrown at ext/web/06_streams.js:6765

  respondWithNewView(view) {
    webidl.assertBranded(this, ReadableStreamBYOBRequestPrototype);
    const prefix =
      "Failed to execute 'respondWithNewView' on 'ReadableStreamBYOBRequest'";
    webidl.requiredArguments(arguments.length, 1, prefix);
    view = webidl.converters.ArrayBufferView(view, prefix, "Argument 1");

    if (this[_controller] === undefined) {
      throw new TypeError("This BYOB request has been invalidated");
    }

    let buffer;
    if (isTypedArray(view)) {
      buffer = TypedArrayPrototypeGetBuffer(view);
    } else {
      buffer = DataViewPrototypeGetBuffer(view);
    }
    if (isDetachedBuffer(buffer)) {
      throw new TypeError(
        "The given view's buffer has been detached and so cannot be used as a response",
      );
    }
    readableByteStreamControllerRespondWithNewView(this[_controller], view);
  }
}

webidl.configureInterface(ReadableStreamBYOBRequest);
const ReadableStreamBYOBRequestPrototype = ReadableStreamBYOBRequest.prototype;

class ReadableByteStreamController {
  /** @type {number | undefined} */
  [_autoAllocateChunkSize];
  /** @type {ReadableStreamBYOBRequest | null} */
  [_byobRequest];
  /** @type {(reason: any) => Promise<void>} */
  [_cancelAlgorithm];
  /** @type {boolean} */

View on GitHub (pinned to 9ad36f7a2c)

Solutions

  1. Allocate a fresh Uint8Array with its own buffer and pass that to respondWithNewView().
  2. Remove the buffer from any transfer list before calling respondWithNewView(); transfer only after respond completes.
  3. If data must move realms first, respond() with a byte count against a still-attached buffer after copying into it.

Example fix

// before
const view = new Uint8Array(1024);
postMessage(view.buffer, [view.buffer]); // detached
byobRequest.respondWithNewView(view); // TypeError

// after
const view = new Uint8Array(1024);
fill(view);
byobRequest.respondWithNewView(view); // still attached
postMessage(result, []); // transfer later, if still needed
Defensive patterns

Strategy: type-guard

Validate before calling

function isAttachedView(view) {
  return (
    view != null &&
    ArrayBuffer.isView(view) &&
    view.byteLength > 0 &&
    view.buffer.byteLength > 0
  );
}
if (!isAttachedView(view)) view = new Uint8Array(newBytes); // fresh, owned
byobRequest.respondWithNewView(view);

Type guard

function isAttachedView(view) {
  return view != null && ArrayBuffer.isView(view) &&
    view.buffer.byteLength > 0 && (view.buffer.detached !== true);
}

Try / catch

try {
  byobRequest.respondWithNewView(view);
} catch (err) {
  if (err instanceof TypeError && /detached/.test(err.message)) {
    byobRequest.respondWithNewView(new Uint8Array(copyOfData));
  } else throw err;
}

Prevention

When it happens

Trigger: Calling respondWithNewView(view) where view.buffer was transferred via view.buffer.transfer(), included in a postMessage/structuredClone transfer list, or otherwise detached before the call. Also passing a view over a pooled/SLAB buffer that was already transferred by earlier async code.

Common situations: Zero-copy designs that transfer buffers to Workers and then try to respond with the moved-out view; reusing a view object after its buffer was recycled; refactors that move the transfer step before the respond step.

Related errors


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