denoland/deno · error · RangeError

The region specified by view does not match byobRequest

Error message

The region specified by view does not match byobRequest

What it means

RangeError from respondWithNewView(view): the view's byteOffset does not equal firstDescriptor.byteOffset + firstDescriptor.bytesFilled. The BYOB protocol requires the replacement view to start exactly where the request left off inside the consumer's buffer; any other offset is rejected before the buffer is transferred back.

Source

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

  const firstDescriptor = controller[_pendingPullIntos].peek();
  const state = controller[_stream][_state];
  if (state === "closed") {
    if (byteLength !== 0) {
      throw new TypeError(
        `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);
}

View on GitHub (pinned to 9ad36f7a2c)

Solutions

  1. Default to byob.respond(n) — offset bookkeeping is then handled for you.
  2. When you must supply a new view, derive it from the request's own view so the offset matches the fill point.
  3. Verify view.byteOffset matches byob.view.byteOffset (plus any bytes already filled) before responding.

Example fix

// before
const out = new Uint8Array(n); // offset 0, fresh buffer
byob.respondWithNewView(out);   // fill point is not 0 -> RangeError

// after
const v = byob.view;         // the request's own view, correct offset
writeInto(v);                // fill starting at the current fill point
byob.respond(v.byteLength);
Defensive patterns

Strategy: validation

Validate before calling

// the new view must start where the request left off
if (view.byteOffset !== byob.view.byteOffset) {
  view = byob.view; // fall back to the handed-out view
}
byob.respondWithNewView(view);

Try / catch

try {
  byob.respondWithNewView(view);
} catch (e) {
  if (e instanceof RangeError && e.message.includes('does not match byobRequest')) {
    byob.respond(byob.view.byteLength); // respond with the original view instead
    return;
  }
  throw e;
}

Prevention

When it happens

Trigger: Passing a view at offset 0 when a partial fill already advanced the fill point; passing a view over a different buffer; constructing a fresh Uint8Array for the response instead of reusing the request's own view; slicing with the wrong start index.

Common situations: Decode/encode steps that wrap output in a newly allocated view; responding with view.subarray(k) for the wrong k; copying request templates from non-BYOB example code.

Related errors


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