denoland/deno · error · TypeError
"bytesWritten" must be greater than 0 when calling respond()
Error message
"bytesWritten" must be greater than 0 when calling respond() on a readable stream
What it means
ReadableStreamBYOBRequest.respond() was called with bytesWritten = 0 while the stream is still 'readable'. A zero-byte respond cannot satisfy the pending BYOB read, so the spec requires at least one byte; 'no bytes available' must instead be expressed by closing the stream (or by returning a pending promise from pull()).
Source
Thrown at ext/web/06_streams.js:2600
/**
* @param {ReadableByteStreamController} controller
* @param {number} bytesWritten
* @returns {void}
*/
function readableByteStreamControllerRespond(controller, bytesWritten) {
assert(controller[_pendingPullIntos].size !== 0);
const firstDescriptor = controller[_pendingPullIntos].peek();
const state = controller[_stream][_state];
if (state === "closed") {
if (bytesWritten !== 0) {
throw new TypeError(
`"bytesWritten" must be 0 when calling respond() on a closed stream: received ${bytesWritten}`,
);
}
} else {
assert(state === "readable");
if (bytesWritten === 0) {
throw new TypeError(
'"bytesWritten" must be greater than 0 when calling respond() on a readable stream',
);
}
if (
(firstDescriptor.bytesFilled + bytesWritten) >
// deno-lint-ignore deno-internal/prefer-primordials
firstDescriptor.byteLength
) {
throw new RangeError('"bytesWritten" out of range');
}
}
firstDescriptor.buffer = ArrayBufferPrototypeTransferToFixedLength(
// deno-lint-ignore deno-internal/prefer-primordials
firstDescriptor.buffer,
);
readableByteStreamControllerRespondInternal(controller, bytesWritten);
}
View on GitHub (pinned to 9ad36f7a2c)
Solutions
- Treat bytesRead === 0 as EOF: call controller.close() and return without responding.
- If the operation failed, call controller.error(err) instead of respond(0).
- Only call respond(n) after actually writing n >= 1 bytes into byobRequest.view.
Example fix
// before
const { bytesRead } = await read(fd, byob.view);
byob.respond(bytesRead); // bytesRead === 0 -> TypeError: must be greater than 0
// after
const { bytesRead } = await read(fd, byob.view);
if (bytesRead === 0) { controller.close(); return; } // EOF
byob.respond(bytesRead); Defensive patterns
Strategy: validation
Validate before calling
if (bytesRead === 0) { controller.close(); return; } // EOF, not respond(0)
if (controller.byobRequest !== null) controller.byobRequest.respond(bytesRead); Try / catch
try {
byob.respond(n);
} catch (e) {
if (e instanceof TypeError && e.message.includes('must be greater than 0')) {
controller.close(); // zero bytes on a readable stream means EOF
return;
}
throw e;
} Prevention
- Map every zero-byte read to close() and every failed read to controller.error().
- Never use respond(0) as a 'nothing happened' signal — return a pending promise from pull() instead.
When it happens
Trigger: An OS read into byobRequest.view returns 0 bytes (EOF) and the adapter calls byob.respond(0) instead of controller.close(); an error path that 'responds with nothing' rather than calling controller.error(err).
Common situations: Adapting POSIX read()/file descriptors or sockets to a type: 'bytes' stream; TCP reads returning 0 on peer disconnect; loops copied from default-reader code where signaling emptiness is legal.
Related errors
- "bytesWritten" must be 0 when calling respond() on a closed
- "bytesWritten" out of range
- The view's length must be greater than 0 when calling respon
- This BYOB request has been invalidated
- The BYOB request's buffer has been detached and so cannot be
AI-assisted analysis of denoland/deno@9ad36f7a2c (2026-08-20).
Data as JSON: /api/errors/93741a3f0bd95fcc.
Report an issue: GitHub.