denoland/deno · error · RangeError

The buffer of view has different capacity than byobRequest

Error message

The buffer of view has different capacity than byobRequest

What it means

RangeError from respondWithNewView(view): the view's backing ArrayBuffer has a different byteLength than the pending pull-into's bufferByteLength (the capacity when the read started). The replacement view must live over the same-sized buffer — normally the exact buffer handed out — so the transfer back to the consumer stays consistent.

Source

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

        `The view's length must be 0 when calling respondWithNewView() on a closed stream: received ${byteLength}`,
      );
    }
  } else {
    assert(state === "readable");
    if (byteLength === 0) {
      throw new TypeError(
        "The view's length must be greater than 0 when calling respondWithNewView() on a readable stream",
      );
    }
  }
  // deno-lint-ignore deno-internal/prefer-primordials
  if (firstDescriptor.byteOffset + firstDescriptor.bytesFilled !== byteOffset) {
    throw new RangeError(
      "The region specified by view does not match byobRequest",
    );
  }
  if (firstDescriptor.bufferByteLength !== getArrayBufferByteLength(buffer)) {
    throw new RangeError(
      "The buffer of view has different capacity than byobRequest",
    );
  }
  // deno-lint-ignore deno-internal/prefer-primordials
  if (firstDescriptor.bytesFilled + byteLength > firstDescriptor.byteLength) {
    throw new RangeError(
      "The region specified by view is larger than byobRequest",
    );
  }
  firstDescriptor.buffer = ArrayBufferPrototypeTransferToFixedLength(buffer);
  readableByteStreamControllerRespondInternal(controller, byteLength);
}

/**
 * @param {ReadableByteStreamController} controller
 * @returns {PullIntoDescriptor}
 */
function readableByteStreamControllerShiftPendingPullInto(controller) {

View on GitHub (pinned to 9ad36f7a2c)

Solutions

  1. Write into byobRequest.view and call respond(n) — allocation-free and always consistent.
  2. If you must respondWithNewView, use a view over the request's original buffer with the same capacity.
  3. Never allocate a fresh buffer as the response region.

Example fix

// before
const decoded = decodeIntoNewBuffer(byob.view);  // allocates a new buffer
byob.respondWithNewView(new Uint8Array(decoded)); // capacity differs -> RangeError

// after
const n = decodeInto(byob.view); // writes into the request's buffer
byob.respond(n);
Defensive patterns

Strategy: validation

Validate before calling

if (view.buffer !== byob.view.buffer) {
  view = byob.view; // response region must live in the handed-out buffer
}
byob.respondWithNewView(view);

Try / catch

try {
  byob.respondWithNewView(view);
} catch (e) {
  if (e instanceof RangeError && e.message.includes('different capacity')) {
    byob.respond(byob.view.byteLength);
    return;
  }
  throw e;
}

Prevention

When it happens

Trigger: Wrapping output in a newly allocated ArrayBuffer instead of using the request's buffer; detaching and recreating the consumer buffer between read(view) and respond; re-wrapping a resized buffer after transfer.

Common situations: Decode steps that allocate a new buffer per chunk; Node-style 'allocate a result and return it' patterns applied to BYOB responses; growable buffers resized in between.

Related errors


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