{"record":{"id":"1ba7e6a03f4b6018","repo":"denoland/deno","slug":"unsupported-keyobject-type-for-structured-clone","errorCode":null,"errorMessage":"Unsupported KeyObject type for structured clone: ${data.keyType}","messagePattern":"Unsupported KeyObject type for structured clone: (.+?)","errorType":"exception","errorClass":"TypeError","httpStatus":null,"severity":"error","filePath":"ext/node/polyfills/internal/crypto/keys.ts","lineNumber":1120,"sourceCode":"      const handle = op_node_create_public_key(\n        data.keyData,\n        \"der\",\n        \"spki\",\n        undefined,\n      );\n      return new PublicKeyObject(handle);\n    }\n    case \"private\": {\n      const handle = op_node_create_private_key(\n        data.keyData,\n        \"der\",\n        \"pkcs8\",\n        undefined,\n      );\n      return new PrivateKeyObject(handle);\n    }\n    default:\n      throw new TypeError(\n        `Unsupported KeyObject type for structured clone: ${data.keyType}`,\n      );\n  }\n}\n\nreturn {\n  getArrayBufferOrView,\n  deserializeNodeCryptoKeyObject,\n  KeyObject,\n  kConsumePublic,\n  kConsumePrivate,\n  kCreatePublic,\n  kCreatePrivate,\n  createPrivateKey,\n  createPublicKey,\n  createSecretKey,\n  prepareSecretKey,\n  prepareAsymmetricKey,","sourceCodeStart":1102,"sourceCodeEnd":1138,"githubUrl":"https://github.com/denoland/deno/blob/9ad36f7a2cce60488e6ec52283efb32efddaf93a/ext/node/polyfills/internal/crypto/keys.ts#L1102-L1138","documentation":"deserializeNodeCryptoKeyObject is the structured-clone deserializer that resurrects node:crypto KeyObjects across postMessage/structuredClone boundaries. It only recognizes keyType 'secret', 'public' and 'private' from the internal NodeCryptoKeyObject brand; any other value falls into the default branch and throws this TypeError. Hitting it means the serialized payload was not produced by a matching Deno KeyObject implementation — version mismatch, hand-crafted clone data, or corruption.","triggerScenarios":"worker.postMessage(keyObject) where the receiving side runs a Deno build whose KeyObject brand differs; structuredClone over an object manually shaped like { type: 'NodeCryptoKeyObject', keyType: 'foo', keyData } ; restoring persisted structured-clone blobs after a runtime upgrade.","commonSituations":"Main thread and workers on different Deno versions (or Deno vs another runtime that emits a lookalike brand); persisting structured-clone output of KeyObjects and restoring it later; library code that wraps/spreads KeyObjects before sending them through the clone pipeline.","solutions":["Transfer raw key material instead: export on the sender (keyObject.export()) and reconstruct on the receiver with createSecretKey/createPublicKey/createPrivateKey","Pin the main thread and all workers to the same runtime version","Never persist or hand-build the internal NodeCryptoKeyObject clone shape — treat it as an implementation detail of the current Deno version"],"exampleFix":"// before\nworker.postMessage(secretKeyObject); // relies on internal clone brand\n\n// after\nworker.postMessage({ kind: 'secret', raw: secretKeyObject.export() });\n// in the worker:\nconst key = createSecretKey(msg.raw);","handlingStrategy":"validation","validationCode":"// Before posting a key to a worker, send plain data and rebuild it there.\nif (isKeyObject(value)) {\n  worker.postMessage({\n    kind: 'key',\n    keyType: value.type,\n    raw: value.type === 'secret' ? value.export() : value.export({ format: 'der', type: 'pkcs8' }),\n  });\n} else {\n  worker.postMessage(value);\n}","typeGuard":"const KNOWN_KEY_TYPES = new Set(['secret', 'public', 'private']);\nfunction isCloneableNodeCryptoKeyObject(data: unknown): data is { keyType: string } {\n  return typeof data === 'object' && data !== null &&\n    KNOWN_KEY_TYPES.has((data as { keyType?: string }).keyType as string);\n}","tryCatchPattern":"// inside the worker's message handler\nself.onmessage = (ev) => {\n  try {\n    handle(ev.data);\n  } catch (e) {\n    if (e instanceof TypeError && /structured clone/.test(e.message)) {\n      // sender/runtime mismatch: request the sender re-send raw key bytes\n    } else throw e;\n  }\n};","preventionTips":["Do not rely on internal structured-clone brands for KeyObjects across runtimes or versions","Transfer key material as bytes and reconstruct with createSecretKey/createPrivateKey","Pin worker and main-thread runtime versions in deployment; treat clone payloads as version-specific"],"tags":["crypto","structured-clone","workers","node-compat","keyobject"],"backgroundTag":"structured-clone-unsupported-type","analyzedSha":"9ad36f7a2cce60488e6ec52283efb32efddaf93a","analyzedAt":"2026-08-20T13:07:44.778Z","schemaVersion":2},"datasetVersion":"2026-08-21T13:17:26.733Z"}