denoland/deno · error · TypeError
A chunk may only be either a string or an Uint8Array
Error message
A chunk may only be either a string or an Uint8Array
What it means
The writable side of a WebSocketStream only accepts strings and Uint8Arrays: the write() implementation checks typeof chunk === 'string' or the typed-array tag 'Uint8Array'. Anything else - ArrayBuffer, DataView, other typed arrays, Blob, plain objects, numbers - throws a plain TypeError from inside the stream.
Source
Thrown at ext/websocket/02_websocketstream.js:224
const err = new WebSocketError("Closed while connecting");
this[_opened].reject(err);
this[_closed].reject(err);
},
);
} else {
this[_rid] = create.rid;
const writable = new WritableStream({
write: async (chunk) => {
if (typeof chunk === "string") {
await op_ws_send_text_async(this[_rid], chunk);
} else if (
TypedArrayPrototypeGetSymbolToStringTag(chunk) ===
"Uint8Array"
) {
await op_ws_send_binary_async(this[_rid], chunk);
} else {
throw new TypeError(
"A chunk may only be either a string or an Uint8Array",
);
}
},
close: async () => {
this.close();
await this.closed;
},
abort: async (reason) => {
let closeCode = null;
let reasonString = "";
if (
ObjectPrototypeIsPrototypeOf(WebSocketErrorPrototype, reason)
) {
closeCode = reason.closeCode;
reasonString = reason.reason;
}View on GitHub (pinned to 9ad36f7a2c)
Solutions
- Encode text to bytes: new TextEncoder().encode(str)
- Wrap buffers: new Uint8Array(arrayBuffer)
- Stringify structured data: JSON.stringify(value)
- Convert Blob: new Uint8Array(await blob.arrayBuffer())
Example fix
// before
await writer.write({ type: 'msg' });
await writer.write(await file.arrayBuffer()); // ArrayBuffer
// after
await writer.write(JSON.stringify({ type: 'msg' }));
await writer.write(new Uint8Array(await file.arrayBuffer())); Defensive patterns
Strategy: type-guard
Validate before calling
function toChunk(v: unknown): string | Uint8Array {
if (typeof v === 'string') return v;
if (v instanceof Uint8Array) return v;
if (v instanceof ArrayBuffer) return new Uint8Array(v);
if (typeof v === 'object' && v !== null) return JSON.stringify(v);
throw new TypeError('unsupported chunk type');
}
await writer.write(toChunk(data)); Type guard
const isWsChunk = (v: unknown): v is string | Uint8Array => typeof v === 'string' || v instanceof Uint8Array;
Prevention
- Writable chunks must be string or Uint8Array - nothing else
- Blob works on WebSocket.send but NOT on WebSocketStream.writable
- Put one normalize/encode helper at the write boundary and use it everywhere
When it happens
Trigger: writer.write(new ArrayBuffer(8)), writer.write(new Uint16Array(4)), writer.write(blob) (allowed on WebSocket.send but not here), writer.write({ data }) without JSON.stringify, writer.write(42).
Common situations: Assuming ws.send()-compatible types carry over to WebSocketStream; forgetting JSON.stringify for objects; passing a raw ArrayBuffer from file/socket reads instead of a Uint8Array view.
Related errors
- Expected the second argument to assertSnapshot() to be an op
- Snapshot serializer must return a string
- Cannot access pointer: expected 'ArrayBuffer', 'SharedArrayB
- Deno.Kv can not be constructed: use Deno.openKv instead
- Value must be a bigint: received ${typeof value}
AI-assisted analysis of denoland/deno@9ad36f7a2c (2026-08-20).
Data as JSON: /api/errors/4e9bbafbf38c01b3.
Report an issue: GitHub.