denoland/deno · error · TypeError
Unsupported KeyObject type for structured clone: ${data.keyT
Error message
Unsupported KeyObject type for structured clone: ${data.keyType} What it means
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.
Source
Thrown at ext/node/polyfills/internal/crypto/keys.ts:1120
const handle = op_node_create_public_key(
data.keyData,
"der",
"spki",
undefined,
);
return new PublicKeyObject(handle);
}
case "private": {
const handle = op_node_create_private_key(
data.keyData,
"der",
"pkcs8",
undefined,
);
return new PrivateKeyObject(handle);
}
default:
throw new TypeError(
`Unsupported KeyObject type for structured clone: ${data.keyType}`,
);
}
}
return {
getArrayBufferOrView,
deserializeNodeCryptoKeyObject,
KeyObject,
kConsumePublic,
kConsumePrivate,
kCreatePublic,
kCreatePrivate,
createPrivateKey,
createPublicKey,
createSecretKey,
prepareSecretKey,
prepareAsymmetricKey,View on GitHub (pinned to 9ad36f7a2c)
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
Example fix
// before
worker.postMessage(secretKeyObject); // relies on internal clone brand
// after
worker.postMessage({ kind: 'secret', raw: secretKeyObject.export() });
// in the worker:
const key = createSecretKey(msg.raw); Defensive patterns
Strategy: validation
Validate before calling
// Before posting a key to a worker, send plain data and rebuild it there.
if (isKeyObject(value)) {
worker.postMessage({
kind: 'key',
keyType: value.type,
raw: value.type === 'secret' ? value.export() : value.export({ format: 'der', type: 'pkcs8' }),
});
} else {
worker.postMessage(value);
} Type guard
const KNOWN_KEY_TYPES = new Set(['secret', 'public', 'private']);
function isCloneableNodeCryptoKeyObject(data: unknown): data is { keyType: string } {
return typeof data === 'object' && data !== null &&
KNOWN_KEY_TYPES.has((data as { keyType?: string }).keyType as string);
} Try / catch
// inside the worker's message handler
self.onmessage = (ev) => {
try {
handle(ev.data);
} catch (e) {
if (e instanceof TypeError && /structured clone/.test(e.message)) {
// sender/runtime mismatch: request the sender re-send raw key bytes
} else throw e;
}
}; Prevention
- 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
When it happens
Trigger: 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.
Common situations: 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.
Related errors
- ERR_INVALID_ARG_VALUE
- ERR_CRYPTO_INVALID_KEY_OBJECT_TYPE
- Can not create private key from ${type} key
- can not create secret key from ${type} key
- ERR_CRYPTO_CUSTOM_ENGINE_NOT_SUPPORTED
AI-assisted analysis of denoland/deno@9ad36f7a2c (2026-08-20).
Data as JSON: /api/errors/1ba7e6a03f4b6018.
Report an issue: GitHub.