denoland/deno · error · DOMException
DataCloneError
DataCloneError
Error message
${err} What it means
Inside a dedicated worker, the global postMessage (DedicatedWorkerGlobalScope, runtime/js/99_main.js) serializes with the same structured-clone machinery as the host side. The fast path (no transfer argument) runs serializeMessageData and wraps serialization failures as a DOMException named DataCloneError with the serializer's message. Non-cloneable values — functions above all — are rejected before anything reaches the parent.
Source
Thrown at runtime/js/99_main.js:252
}
isClosing = true;
op_worker_close();
}
function postMessage(message, transferOrOptions = { __proto__: null }) {
const prefix =
"Failed to execute 'postMessage' on 'DedicatedWorkerGlobalScope'";
webidl.requiredArguments(arguments.length, 1, prefix);
// Fast path: no transferables
if (
transferOrOptions === undefined ||
transferOrOptions === null ||
(arguments.length <= 1)
) {
op_worker_post_message_raw(
messagePort.serializeMessageData(message, (err) => {
throw new DOMException(err, "DataCloneError");
}),
);
return;
}
message = webidl.converters.any(message);
let options;
if (
webidl.type(transferOrOptions) === "Object" &&
transferOrOptions !== undefined &&
transferOrOptions[SymbolIterator] !== undefined
) {
const transfer = webidl.converters["sequence<object>"](
transferOrOptions,
prefix,
"Argument 2",
);
options = { transfer };
} else {View on GitHub (pinned to f7822238ca)
Solutions
- Post plain, structured-clone-safe result data (primitives, plain objects, typed arrays, Map/Set, Date)
- Pre-validate locally with `structuredClone(message)` — it applies the same rules and fails at the true call site
- Use the transfer array for ArrayBuffers: `self.postMessage(data, [buf])`
- Keep functions in the worker; send an id the parent can correlate
Example fix
// before (inside the worker)
self.postMessage({ handler: onDone, value });
// after
self.postMessage({ type: 'done', value }); Defensive patterns
Strategy: try-catch
Validate before calling
structuredClone(message); // throws DataCloneError locally if the payload is not cloneable self.postMessage(message);
Try / catch
try {
self.postMessage(result);
} catch (e) {
if (e instanceof DOMException && e.name === 'DataCloneError') {
self.postMessage({ type: 'error', message: 'result not cloneable' });
} else {
throw e;
}
} Prevention
- Run worker results through structuredClone() before posting to fail at the source
- Keep result objects plain — strip callbacks, class instances, and live handles before sending
- Use the transfer array for ArrayBuffers being handed off to the parent
When it happens
Trigger: `self.postMessage({ handler: onDone })` inside the worker; posting class instances with own function properties or live native handles; sending a message containing a promise or symbol-keyed behavior object.
Common situations: Worker result objects that accidentally include callbacks or class instances; sharing request-scoped objects back to the parent; code moved from a same-thread context where references were passed around.
Related errors
- DataCloneError
- DataCloneError
- DataCloneError
- DataCloneError
- Unsupported KeyObject type for structured clone: ${data.keyT
AI-assisted analysis of denoland/deno@f7822238ca (2026-08-20).
Data as JSON: /api/errors/279a207c23acd53b.
Report an issue: GitHub.