clockworklabs/SpacetimeDB · error · TypeError
Option 'stream' not supported
Error message
Option 'stream' not supported
What it means
The TextDecoder polyfill in the SpacetimeDB V8 host has no streaming decode state: decode(input, options) throws TypeError('Option stream not supported') whenever options.stream is truthy. Each decode() call is independent, so incremental decoding must be done by the caller.
Source
Thrown at crates/core/src/host/v8/builtins/text_encoding.js:57
}
get encoding() {
return this.#encoding;
}
get fatal() {
return this.#fatal;
}
get ignoreBOM() {
return false;
}
/**
* @argument {any} input
* @argument {any} options
*/
decode(input, options = {}) {
if (options.stream) {
throw new TypeError("Option 'stream' not supported");
}
if (input instanceof ArrayBuffer || input instanceof SharedArrayBuffer) {
input = new Uint8Array(input);
}
return utf8_decode(input, this.#fatal);
}
};
View on GitHub (pinned to 524b4487d9)
Solutions
- Accumulate chunks in a buffer and call decode() once, without options, when the message is complete
- If every chunk is message-complete and ends on a UTF-8 codepoint boundary (true for frames you framed yourself), call decode(chunk) with no options
- Move incremental decoding of untrusted/boundary-split streams outside the module
Example fix
// before
for (const chunk of chunks) parts.push(dec.decode(chunk, { stream: true }));
// after
let buf = new Uint8Array(0);
for (const chunk of chunks) {
const merged = new Uint8Array(buf.length + chunk.length);
merged.set(buf); merged.set(chunk, buf.length);
buf = merged;
}
const text = dec.decode(buf); Defensive patterns
Strategy: validation
Validate before calling
function decodeAll(dec: TextDecoder, chunks: Uint8Array[]): string {
if (chunks.length === 1) return dec.decode(chunks[0]);
const total = chunks.reduce((n, c) => n + c.length, 0);
const buf = new Uint8Array(total);
let off = 0;
for (const c of chunks) { buf.set(c, off); off += c.length; }
return dec.decode(buf); // no options: stream is unsupported
} Type guard
function isStreamSafe(chunks: Uint8Array[]): boolean {
// Safe only if each chunk is a complete message; conservative default: false
return chunks.length <= 1;
} Try / catch
try {
text = dec.decode(chunk, options);
} catch (e) {
if (e instanceof TypeError && /stream/.test(e.message)) {
pending.push(chunk); // buffer and decode once complete
} else throw e;
} Prevention
- Design protocols so each message is a complete UTF-8 payload
- Never pass option objects to decode() verbatim; drop stream explicitly
- Buffer chunks and decode once at message end instead of incrementally
When it happens
Trigger: Calling decoder.decode(chunk, { stream: true }) while feeding chunked data (websocket frames, file reads, socket streams) into the decoder.
Common situations: Porting streaming parsers from browsers/Node that rely on BOM/state carry-over between decode calls; handling large payloads split across messages.
Related errors
- The encoding label provided is invalid
- Option 'ignoreBOM' not supported
- Math.random is not available in SpacetimeDB modules. Use ctx
- must export schema as default export
- default export is not a Schema object
AI-assisted analysis of clockworklabs/SpacetimeDB@524b4487d9 (2026-08-16).
Data as JSON: /api/errors/fa559caf1fd8609e.
Report an issue: GitHub.