{"record":{"id":"8d0f3c14135a5399","repo":"denoland/deno","slug":"invalid-key-type","errorCode":null,"errorMessage":"Invalid key type","messagePattern":"Invalid key type","errorType":"exception","errorClass":"TypeError","httpStatus":null,"severity":"error","filePath":"ext/node/polyfills/internal/crypto/cipher.ts","lineNumber":911,"sourceCode":"    const data = key.export({ type: \"pkcs8\", format: \"pem\" });\n    return { data: getArrayBufferOrView(data, \"key\") };\n  } else if (typeof key == \"object\") {\n    const { key: data, encoding, passphrase, format, type } = key;\n    if (isKeyObject(data)) {\n      return prepareKey(data);\n    }\n    if (format === \"jwk\") {\n      // Build a KeyObject from the JWK and export it as PEM so the\n      // downstream op can consume it via the existing PEM parsing path.\n      const isPrivate = typeof data === \"object\" && data !== null &&\n        typeof (data as { d?: unknown }).d === \"string\";\n      const keyObject = isPrivate\n        ? createPrivateKey({ key: data, format: \"jwk\" })\n        : createPublicKey({ key: data, format: \"jwk\" });\n      return prepareKey(keyObject);\n    }\n    if (!isStringOrBuffer(data)) {\n      throw new TypeError(\"Invalid key type\");\n    }\n\n    // If a passphrase is supplied with raw key material, decrypt the key via\n    // the native key handle and re-export as unencrypted PKCS#8 PEM so the\n    // downstream RSA ops can parse it.\n    if (passphrase != null) {\n      const keyFormat = format ?? (typeof data === \"string\" ? \"pem\" : \"der\");\n      const keyData = getArrayBufferOrView(data, \"key\", encoding);\n      const passphraseData = getArrayBufferOrView(passphrase, \"passphrase\");\n      const handle = op_node_create_private_key(\n        keyData,\n        keyFormat,\n        type ?? \"\",\n        passphraseData,\n      );\n      const pem = op_node_export_private_key_pem(\n        handle,\n        \"pkcs8\",","sourceCodeStart":893,"sourceCodeEnd":929,"githubUrl":"https://github.com/denoland/deno/blob/9ad36f7a2cce60488e6ec52283efb32efddaf93a/ext/node/polyfills/internal/crypto/cipher.ts#L893-L929","documentation":"prepareKey (cipher.ts:911) throws this TypeError when the key argument is an options object ({ key, encoding, passphrase, format }) but the nested key value is neither string nor binary data. KeyObjects of type 'public'/'private', and { format: 'jwk' } payloads, are handled earlier, so this fires for objects whose key field is the wrong thing — including secret-type KeyObjects, which do not match the public/private branches.","triggerScenarios":"publicEncrypt({ key: 123 }, data); publicEncrypt({ key: { pem } }, data) — double-wrapped options; passing a secret KeyObject from createSecretKey() (only 'public'/'private' types are recognized at the top level, and the object branch then finds no usable .key field); a parsed JSON document passed instead of its string field.","commonSituations":"createSecretKey bytes reused for RSA operations; KMS/JWKS wrappers not unwrapped before use; variable naming where `key` accidentally holds a container rather than the material.","solutions":["Pass the PEM string or DER Buffer directly, or a KeyObject from createPublicKey/createPrivateKey","Unwrap nested structures so options.key is the raw key material itself","For JWK input set format: 'jwk' so the dedicated branch runs","Never feed secret-type KeyObjects to the RSA encrypt/decrypt functions"],"exampleFix":"// before\npublicEncrypt({ key: { pem: pemString } }, data); // Invalid key type\n\n// after\npublicEncrypt(pemString, data);\n// or\npublicEncrypt(createPublicKey(pemString), data);","handlingStrategy":"type-guard","validationCode":"import { isKeyObject } from 'node:crypto';\nfunction isRawKeyMaterial(v) {\n  return typeof v === 'string' || ArrayBuffer.isView(v) || v instanceof ArrayBuffer;\n}\nfunction assertPrepareable(key) {\n  if (isRawKeyMaterial(key) || isKeyObject(key)) return;\n  if (key && typeof key === 'object') {\n    if (isKeyObject(key.key) || key.format === 'jwk' || isRawKeyMaterial(key.key)) return;\n  }\n  throw new TypeError('Invalid key type');\n}","typeGuard":"function isAcceptableKeyArg(k) {\n  if (typeof k === 'string' || ArrayBuffer.isView(k) || k instanceof ArrayBuffer) return true;\n  if (isKeyObject(k) && (k.type === 'public' || k.type === 'private')) return true;\n  if (k && typeof k === 'object') {\n    return isKeyObject(k.key) || k.format === 'jwk' || typeof k.key === 'string' || ArrayBuffer.isView(k.key);\n  }\n  return false;\n}","tryCatchPattern":null,"preventionTips":["Construct KeyObjects once (createPublicKey/createPrivateKey) and pass those around","Never double-wrap: options.key must be the key material itself, not a container","Reject secret-type KeyObjects early on RSA encrypt/decrypt code paths"],"tags":["crypto","rsa","key-management","validation"],"backgroundTag":"invalid-key-format","analyzedSha":"9ad36f7a2cce60488e6ec52283efb32efddaf93a","analyzedAt":"2026-08-20T13:07:44.778Z","schemaVersion":2},"datasetVersion":"2026-08-21T13:17:26.733Z"}