denoland/deno · error · TypeError

The view's length must be 0 when calling respondWithNewView(

Error message

The view's length must be 0 when calling respondWithNewView() on a closed stream: received ${byteLength}

What it means

ReadableStreamBYOBRequest.respondWithNewView(view) was called with a non-zero-length view after the stream closed. On a closed stream the pending pull-into can only be acknowledged with an empty region (a zero-length view, or respond(0)); there is no consumer buffer left to deliver bytes into.

Source

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

    buffer = TypedArrayPrototypeGetBuffer(/** @type {Uint8Array}} */ (view));
    byteLength = TypedArrayPrototypeGetByteLength(
      /** @type {Uint8Array} */ (view),
    );
    byteOffset = TypedArrayPrototypeGetByteOffset(
      /** @type {Uint8Array} */ (view),
    );
  } else {
    buffer = DataViewPrototypeGetBuffer(/** @type {DataView} */ (view));
    byteLength = DataViewPrototypeGetByteLength(/** @type {DataView} */ (view));
    byteOffset = DataViewPrototypeGetByteOffset(/** @type {DataView} */ (view));
  }

  assert(!isDetachedBuffer(buffer));
  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)) {

View on GitHub (pinned to 9ad36f7a2c)

Solutions

  1. Prefer respond(n) over respondWithNewView unless you must hand back a different region; on a closed stream respond(0) is the only legal acknowledgment.
  2. Skip responding entirely once controller.byobRequest is null or the stream is closed.
  3. Await pending operations before calling controller.close().

Example fix

// before
if (finished) controller.close();
byob.respondWithNewView(view); // non-empty view after close -> TypeError

// after
if (finished) { controller.close(); return; }
byob.respond(view.byteLength); // stream still readable here
Defensive patterns

Strategy: validation

Validate before calling

if (controller.byobRequest === null) return; // closed or no pending read
if (view.byteLength === 0) controller.byobRequest.respond(0); // legal ack on closed streams
else controller.byobRequest.respondWithNewView(view);

Try / catch

try {
  byob.respondWithNewView(view);
} catch (e) {
  if (e instanceof TypeError && e.message.includes('closed stream')) return;
  throw e;
}

Prevention

When it happens

Trigger: respondWithNewView(filledView) executes after controller.close() ran — e.g. a completion callback fires post-close, or a stale request object is used after the stream finished; a retry path that responds a second time with data.

Common situations: Async I/O completion racing an EOF close; replay/retry logic responding twice; wrapping a library that closes the stream and also invokes a callback expected to respond.

Related errors


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