denoland/deno · error · TypeError
buffer must be a TypedArray or a DataView
Error message
buffer must be a TypedArray or a DataView
What it means
v8.deserialize(buffer) expects the serialized value's backing bytes as a TypedArray or DataView. The polyfill checks isArrayBufferView(buffer) and throws a plain TypeError otherwise, matching Node. A bare ArrayBuffer, a string, or null all fail because the deserializer needs the view's byteOffset and length.
Source
Thrown at ext/node/polyfills/v8.ts:318
if (count === 0) return [];
return [`${count} instance(s) of ${name}`];
}
// Default format returns live object handles, which would require V8's
// `HeapProfiler::QueryObjects` (not exposed in rusty_v8). Returning an
// empty array keeps the signature sensible.
return [];
}
// deno-lint-ignore no-explicit-any
function serialize(value: any) {
const ser = new DefaultSerializer();
ser.writeHeader();
ser.writeValue(value);
return ser.releaseBuffer();
}
function deserialize(buffer: Buffer | ArrayBufferView | DataView) {
if (!isArrayBufferView(buffer)) {
throw new TypeError(
"buffer must be a TypedArray or a DataView",
);
}
const der = new DefaultDeserializer(buffer);
der.readHeader();
return der.readValue();
}
const kHandle = Symbol("kHandle");
const kHeaderWritten = Symbol("kHeaderWritten");
class Serializer {
[kHandle]: object;
[kHeaderWritten] = false;
constructor() {
this[kHandle] = op_v8_new_serializer(this);
}
View on GitHub (pinned to 9ad36f7a2c)
Solutions
- Wrap the buffer in a view: v8.deserialize(new Uint8Array(arrayBuffer)).
- Use Buffer.from(data) (or Buffer.concat(chunks)) for network/file payloads before deserializing.
- Type the parameter as Buffer | ArrayBufferView | DataView in your API so mistakes surface at compile time.
Example fix
// before const ab = await response.arrayBuffer(); // bare ArrayBuffer const value = v8.deserialize(ab); // TypeError // after const value = v8.deserialize(new Uint8Array(await response.arrayBuffer()));
Defensive patterns
Strategy: type-guard
Validate before calling
function asView(buf) {
return ArrayBuffer.isView(buf) ? buf : new Uint8Array(buf);
}
// then always: v8.deserialize(asView(data)) Type guard
const isBufferView = (v) => ArrayBuffer.isView(v);
Prevention
- Keep v8-serialized bytes in a Buffer/Uint8Array end to end.
- After postMessage or file round trips, re-wrap with Buffer.from before deserializing.
- Remember a bare ArrayBuffer is not accepted — only views over it.
When it happens
Trigger: v8.deserialize(new ArrayBuffer(n)), v8.deserialize(someString), or v8.deserialize(null). A Node Buffer or any TypedArray/DataView passes.
Common situations: Storing v8.serialize() output and then transferring/postMessaging it so it arrives as a bare ArrayBuffer; reading a file or fetch body into an ArrayBuffer and forgetting to wrap; structured-clone round trips that strip the view.
Related errors
- source must be a TypedArray or a DataView
- The "${name}" argument must be of type function. Received ${
- Expected the second argument to assertSnapshot() to be an op
- Snapshot serializer must return a string
- Cannot access pointer: expected 'ArrayBuffer', 'SharedArrayB
AI-assisted analysis of denoland/deno@9ad36f7a2c (2026-08-20).
Data as JSON: /api/errors/5474b6d5cf42686c.
Report an issue: GitHub.