denoland/deno · error · TypeError
Cannot use a BYOB reader with a non-byte stream
Error message
Cannot use a BYOB reader with a non-byte stream
What it means
A BYOB reader was attached to a ReadableStream that is not a byte stream: its controller is a ReadableStreamDefaultController because it was constructed without { type: 'bytes' }, so it fails the ObjectPrototypeIsPrototypeOf(ReadableByteStreamControllerPrototype, ...) check. read-into (BYOB) semantics only exist for byte streams, whose controller can fill caller-provided buffers.
Source
Thrown at ext/web/06_streams.js:4518
);
}
/**
* @template R
* @param {ReadableStreamBYOBReader} reader
* @param {ReadableStream<R>} stream
*/
function setUpReadableStreamBYOBReader(reader, stream) {
if (isReadableStreamLocked(stream)) {
throw new TypeError("ReadableStream is locked");
}
if (
!(ObjectPrototypeIsPrototypeOf(
ReadableByteStreamControllerPrototype,
stream[_controller],
))
) {
throw new TypeError("Cannot use a BYOB reader with a non-byte stream");
}
readableStreamReaderGenericInitialize(reader, stream);
reader[_readIntoRequests] = new Queue();
}
/**
* @template R
* @param {ReadableStreamDefaultReader<R>} reader
* @param {ReadableStream<R>} stream
*/
function setUpReadableStreamDefaultReader(reader, stream) {
if (isReadableStreamLocked(stream)) {
throw new TypeError("ReadableStream is locked");
}
readableStreamReaderGenericInitialize(reader, stream);
reader[_readRequests] = new Queue();
}
View on GitHub (pinned to 9ad36f7a2c)
Solutions
- Create the source as a byte stream: new ReadableStream({ type: 'bytes', ... }).
- Use a default reader (getReader()) when the stream is a value stream.
- If you control the pipeline, funnel value-stream chunks into a byte stream you construct yourself.
Example fix
// before
const stream = new ReadableStream({ start(c) { c.enqueue(new Uint8Array(1)); } });
const reader = stream.getReader({ mode: 'byob' }); // TypeError: non-byte stream
// after
const stream = new ReadableStream({ type: 'bytes', start(c) { c.enqueue(new Uint8Array(1)); } });
const reader = stream.getReader({ mode: 'byob' }); // ok Defensive patterns
Strategy: type-guard
Type guard
function isByteStream(s) {
if (s.locked) return false; // cannot probe while locked
try {
const r = s.getReader({ mode: 'byob' });
r.releaseLock();
return true;
} catch {
return false; // not a byte stream
}
}
const reader = isByteStream(stream)
? stream.getReader({ mode: 'byob' })
: stream.getReader(); Try / catch
try {
reader = stream.getReader({ mode: 'byob' });
} catch (e) {
if (e instanceof TypeError && e.message.includes('non-byte stream')) {
reader = stream.getReader(); // fall back to a default reader
} else throw e;
} Prevention
- BYOB requires the producer's cooperation: { type: 'bytes' } at construction.
- Design helpers to accept a reader and let the caller choose the mode.
- Test generic stream utilities against both byte and value streams.
When it happens
Trigger: stream.getReader({ mode: 'byob' }) or new ReadableStreamBYOBReader(stream) on a stream created via new ReadableStream() without type: 'bytes'; applying a BYOB reader to the readable side of a TransformStream; applying it to framework-produced value streams (fetch bodies, helpers).
Common situations: Generic utility functions that assume all streams are byte streams; adapting a value stream and attempting zero-copy reads; library code that must work on both kinds and probes BYOB support by trying it.
Related errors
- Chunk's buffer is detached and so cannot be enqueued
- The BYOB request's buffer has been detached and so cannot be
- "bytesWritten" must be 0 when calling respond() on a closed
- "bytesWritten" must be greater than 0 when calling respond()
- "bytesWritten" out of range
AI-assisted analysis of denoland/deno@9ad36f7a2c (2026-08-20).
Data as JSON: /api/errors/816d4da49455d01d.
Report an issue: GitHub.