{"record":{"id":"cfef32034f9ada4e","repo":"denoland/deno","slug":"err-crypto-invalid-key-object-type","errorCode":"ERR_CRYPTO_INVALID_KEY_OBJECT_TYPE","errorMessage":"Invalid key object type ${key.type}, expected private.","messagePattern":"Invalid key object type (.+?), expected private\\.","errorType":"error_code","errorClass":"TypeError","httpStatus":null,"severity":"error","filePath":"ext/node/polyfills/internal/crypto/keys.ts","lineNumber":231,"sourceCode":"    // @ts-expect-error __proto__ is magic\n    __proto__: null,\n    configurable: true,\n    value: \"KeyObject\",\n  },\n});\n\nfunction getKeyObjectHandle(key: KeyObject, ctx: number) {\n  if (ctx === kCreatePrivate) {\n    throw new ERR_INVALID_ARG_TYPE(\n      \"key\",\n      [\"string\", \"ArrayBuffer\", \"Buffer\", \"TypedArray\", \"DataView\"],\n      key,\n    );\n  }\n\n  if (key.type !== \"private\") {\n    if (ctx === kConsumePrivate || ctx === kCreatePublic) {\n      throw new ERR_CRYPTO_INVALID_KEY_OBJECT_TYPE(key.type, \"private\");\n    }\n    if (key.type !== \"public\") {\n      throw new ERR_CRYPTO_INVALID_KEY_OBJECT_TYPE(\n        key.type,\n        \"private or public\",\n      );\n    }\n  }\n\n  return key[kHandle];\n}\n\nfunction getKeyObjectHandleFromJwk(key, ctx) {\n  validateObject(key, \"key\");\n  validateOneOf(\n    key.kty,\n    \"key.kty\",\n    [\"RSA\", \"EC\", \"OKP\"],","sourceCodeStart":213,"sourceCodeEnd":249,"githubUrl":"https://github.com/denoland/deno/blob/9ad36f7a2cce60488e6ec52283efb32efddaf93a/ext/node/polyfills/internal/crypto/keys.ts#L213-L249","documentation":"getKeyObjectHandle validates a KeyObject against the operation context. For contexts that require a private key — kConsumePrivate (crypto.sign, the private side of DiffieHellman) and kCreatePublic (crypto.createPublicKey) — a KeyObject whose type is not 'private' throws ERR_CRYPTO_INVALID_KEY_OBJECT_TYPE reporting the actual type and 'expected private'.","triggerScenarios":"crypto.sign(null, data, publicKeyObject); dh.computeSecret(publicKeyObject, privateKeyObject) with the arguments swapped; crypto.createPublicKey(publicKeyObject) — Deno throws where Node tolerantly returns the same key.","commonSituations":"Swapped arguments in diffiehellman.computeSecret; signing with the public key of a pair (PEM mix-ups); re-wrapping a public KeyObject via createPublicKey, a pattern that works on Node but not in the polyfill.","solutions":["Pass the private KeyObject to sign/derive operations; check key.type === 'private' when arguments come from elsewhere","For createPublicKey on a KeyObject, use the existing public KeyObject directly instead of re-wrapping","In shared helpers, branch on the input being a KeyObject vs raw PEM before calling factories"],"exampleFix":"// before\nconst sig = crypto.sign(null, data, publicKeyObject);\n// after\nconst sig = crypto.sign(null, data, privateKeyObject);","handlingStrategy":"validation","validationCode":"function requirePrivateKey(key) {\n  if (!crypto.isKeyObject(key) || key.type !== 'private') {\n    throw new Error(`Expected private KeyObject, got ${key?.type ?? typeof key}`);\n  }\n  return key;\n}\ncrypto.sign(null, data, requirePrivateKey(signingKey));","typeGuard":"function isPrivateKeyObject(k) {\n  return crypto.isKeyObject(k) && k.type === 'private';\n}","tryCatchPattern":"try {\n  return crypto.sign(null, data, key);\n} catch (e) {\n  if (e.code === 'ERR_CRYPTO_INVALID_KEY_OBJECT_TYPE') throw new Error(`Wrong key kind for this op: ${e.message}`);\n  throw e;\n}","preventionTips":["Name variables privateKey/publicKey explicitly to avoid swaps","Check key.type before asymmetric operations","Do not re-wrap public KeyObjects with createPublicKey in portable code"],"tags":["crypto","keyobject","signing","node-compat"],"backgroundTag":"invalid-key-type","analyzedSha":"9ad36f7a2cce60488e6ec52283efb32efddaf93a","analyzedAt":"2026-08-20T13:07:44.778Z","schemaVersion":2},"datasetVersion":"2026-08-21T13:17:26.733Z"}