{"record":{"id":"279a207c23acd53b","repo":"denoland/deno","slug":"datacloneerror-279a20","errorCode":"DataCloneError","errorMessage":"${err}","messagePattern":"\\$\\{err\\}","errorType":"exception","errorClass":"DOMException","httpStatus":null,"severity":"error","filePath":"runtime/js/99_main.js","lineNumber":252,"sourceCode":"  }\n\n  isClosing = true;\n  op_worker_close();\n}\n\nfunction postMessage(message, transferOrOptions = { __proto__: null }) {\n  const prefix =\n    \"Failed to execute 'postMessage' on 'DedicatedWorkerGlobalScope'\";\n  webidl.requiredArguments(arguments.length, 1, prefix);\n  // Fast path: no transferables\n  if (\n    transferOrOptions === undefined ||\n    transferOrOptions === null ||\n    (arguments.length <= 1)\n  ) {\n    op_worker_post_message_raw(\n      messagePort.serializeMessageData(message, (err) => {\n        throw new DOMException(err, \"DataCloneError\");\n      }),\n    );\n    return;\n  }\n  message = webidl.converters.any(message);\n  let options;\n  if (\n    webidl.type(transferOrOptions) === \"Object\" &&\n    transferOrOptions !== undefined &&\n    transferOrOptions[SymbolIterator] !== undefined\n  ) {\n    const transfer = webidl.converters[\"sequence<object>\"](\n      transferOrOptions,\n      prefix,\n      \"Argument 2\",\n    );\n    options = { transfer };\n  } else {","sourceCodeStart":234,"sourceCodeEnd":270,"githubUrl":"https://github.com/denoland/deno/blob/f7822238cab635a3a19f99f493f675fa81a7f9d8/runtime/js/99_main.js#L234-L270","documentation":"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.","triggerScenarios":"`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.","commonSituations":"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.","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"],"exampleFix":"// before (inside the worker)\nself.postMessage({ handler: onDone, value });\n\n// after\nself.postMessage({ type: 'done', value });","handlingStrategy":"try-catch","validationCode":"structuredClone(message); // throws DataCloneError locally if the payload is not cloneable\nself.postMessage(message);","typeGuard":null,"tryCatchPattern":"try {\n  self.postMessage(result);\n} catch (e) {\n  if (e instanceof DOMException && e.name === 'DataCloneError') {\n    self.postMessage({ type: 'error', message: 'result not cloneable' });\n  } else {\n    throw e;\n  }\n}","preventionTips":["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"],"tags":["workers","postmessage","datacloneerror","structured-clone","serialization"],"backgroundTag":"datacloneerror-structured-clone","analyzedSha":"f7822238cab635a3a19f99f493f675fa81a7f9d8","analyzedAt":"2026-08-20T13:07:44.778Z","schemaVersion":2},"datasetVersion":"2026-08-31T14:17:45.589Z"}