denoland/deno · error · DOMException
DataCloneError
DataCloneError
Error message
e.message
What it means
structuredClone delegates to the native structured-clone serializer; when the value graph contains something the algorithm cannot handle (functions, symbols, platform objects without serialization support), the op throws a TypeError which is rewrapped as DOMException DataCloneError carrying the same message (ext/web/02_structured_clone.js:139-143). Only TypeErrors are converted — other exceptions propagate unchanged. This is the same DataCloneError family raised by postMessage on uncloneable data.
Source
Thrown at ext/web/02_structured_clone.js:141
case "Float32Array":
Constructor = Float32Array;
break;
case "Float64Array":
Constructor = Float64Array;
break;
}
return new Constructor(
structuredClone(TypedArrayPrototypeGetBuffer(value)),
TypedArrayPrototypeGetByteOffset(value),
TypedArrayPrototypeGetLength(value),
);
}
try {
return core.structuredClone(value);
} catch (e) {
if (ObjectPrototypeIsPrototypeOf(TypeErrorPrototype, e)) {
throw new DOMException(e.message, "DataCloneError");
}
throw e;
}
}
return { structuredClone };
})();
View on GitHub (pinned to 9ad36f7a2c)
Solutions
- Separate behavior from data: remove functions, symbols, and platform objects before cloning and re-attach them on the receiving side.
- Clone only serializable state (plain objects, arrays, typed arrays, Maps/Sets, Dates, primitives) — the validator/reviver pattern.
- If class instances matter, convert to plain data first and reconstruct from the clone.
- Catch DOMException with name === 'DataCloneError' to emit a targeted error naming the offending key instead of a generic failure.
Example fix
// before
worker.postMessage(structuredClone(ctx)); // ctx has function handlers -> DataCloneError
// after
const { handlers, ...data } = ctx;
worker.postMessage(structuredClone(data)); Defensive patterns
Strategy: try-catch
Validate before calling
function isCloneable(v) {
try { structuredClone(v); return true; } catch { return false; }
}
if (!isCloneable(state)) throw new Error('state contains uncloneable values'); Type guard
const isStructuredCloneable = (v) => {
try { structuredClone(v); return true; } catch { return false; }
}; Try / catch
try {
worker.postMessage(structuredClone(payload));
} catch (e) {
if (e instanceof DOMException && e.name === 'DataCloneError') {
const { handlers, ...data } = payload;
worker.postMessage(structuredClone(data));
} else throw e;
} Prevention
- Keep functions, symbols, and platform objects out of cloned state
- Clone plain data and revive behavior on the receiver
- Type message payloads as plain serializable structures
When it happens
Trigger: structuredClone(() => {}); structuredClone({ cb: function () {} }); structuredClone(Symbol()); cloning an object holding a WebSocket, a Deno platform object, or any class instance whose graph reaches a function or native resource.
Common situations: Sending app state over postMessage/worker messages without stripping handlers; deep-cloning request contexts or ORM entities that embed connections; porting Electron-style IPC patterns where arbitrary objects were tolerated; caching objects that contain callbacks.
Related errors
AI-assisted analysis of denoland/deno@9ad36f7a2c (2026-08-20).
Data as JSON: /api/errors/8aa28a82c7b7607c.
Report an issue: GitHub.