{"record":{"id":"98954e291846e837","repo":"denoland/deno","slug":"datacloneerror-98954e","errorCode":"DataCloneError","errorMessage":"${err}","messagePattern":"\\$\\{err\\}","errorType":"exception","errorClass":"DOMException","httpStatus":null,"severity":"error","filePath":"runtime/js/11_workers.js","lineNumber":329,"sourceCode":"        if (!this.#dispatchWorkerMessage(syncData)) return;\n      }\n    }\n  };\n\n  postMessage(message, transferOrOptions = { __proto__: null }) {\n    const prefix = \"Failed to execute 'postMessage' on 'MessagePort'\";\n    webidl.requiredArguments(arguments.length, 1, prefix);\n    if (this.#status !== \"RUNNING\") return;\n    // Fast path: no transferables\n    if (\n      transferOrOptions === undefined ||\n      transferOrOptions === null ||\n      (arguments.length <= 1)\n    ) {\n      op_host_post_message_raw(\n        this.#id,\n        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":311,"sourceCodeEnd":347,"githubUrl":"https://github.com/denoland/deno/blob/9ad36f7a2cce60488e6ec52283efb32efddaf93a/runtime/js/11_workers.js#L311-L347","documentation":"Worker.postMessage serializes the message with structured clone before handing it to the host. The fast path (no transfer argument) calls serializeMessageData, whose error callback wraps any failure as a DOMException named DataCloneError; the slow path's serializeJsMessageData fails the same way. Values that cannot be cloned include functions, objects with own function properties, and native handles lacking a registered serializer.","triggerScenarios":"`worker.postMessage({ run: () => {} })`; sending promises, bound methods, or class instances carrying own function fields; sending resources (sockets, handles) that Deno has no cross-isolate serializer for; passing a second argument that is neither a transfer array nor options.","commonSituations":"Trying to ship behavior (callbacks) to a worker instead of a message protocol; porting in-process code that shared objects by reference; sending live client objects across isolates.","solutions":["Send plain, structured-clone-safe data: primitives, plain objects/arrays, typed arrays, Map/Set, Date, ArrayBuffer views","Replace callbacks with a request/response protocol — { id, type, payload } over postMessage, results posted back","Transfer (don't copy) ArrayBuffers via the second argument: `worker.postMessage(data, [buf])`","If the worker needs code, import it there, or send source text and evaluate it deliberately"],"exampleFix":"// before\nworker.postMessage({ run: () => heavy(x) }); // DataCloneError\n\n// after\nworker.postMessage({ id: crypto.randomUUID(), type: 'run', payload: x });\n// worker side implements the behavior and posts { id, result } back","handlingStrategy":"try-catch","validationCode":"function hasNonCloneable(value, seen = new WeakSet()) {\n  if (value === null || typeof value !== 'object') return typeof value === 'function';\n  if (seen.has(value)) return false;\n  seen.add(value);\n  return Object.values(value).some((v) => hasNonCloneable(v, seen));\n}\nif (hasNonCloneable(message)) {\n  throw new Error('refusing to postMessage: message contains functions');\n}\nworker.postMessage(message);","typeGuard":null,"tryCatchPattern":"try {\n  worker.postMessage(msg);\n} catch (e) {\n  if (e instanceof DOMException && e.name === 'DataCloneError') {\n    worker.postMessage(JSON.parse(JSON.stringify(msg))); // JSON round-trip drops functions\n  } else {\n    throw e;\n  }\n}","preventionTips":["Restrict worker messages to JSON-safe shapes; define a message type union and construct only those","Validate locally with structuredClone(msg) first — same rules, immediate error at the true call site","Use the transfer array for ArrayBuffers instead of copying large buffers","Design worker RPC as { id, type, payload } messages; never attempt to send behavior"],"tags":["workers","postmessage","datacloneerror","structured-clone","serialization"],"backgroundTag":"datacloneerror-structured-clone","analyzedSha":"9ad36f7a2cce60488e6ec52283efb32efddaf93a","analyzedAt":"2026-08-20T13:07:44.778Z","schemaVersion":2},"datasetVersion":"2026-08-31T14:17:45.589Z"}