{"record":{"id":"05e307fee50fcc2a","repo":"denoland/deno","slug":"err-crypto-sign-key-required","errorCode":"ERR_CRYPTO_SIGN_KEY_REQUIRED","errorMessage":"No key provided to sign","messagePattern":"No key provided to sign","errorType":"error_code","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"ext/node/polyfills/internal/crypto/sig.ts","lineNumber":168,"sourceCode":"      },\n    });\n\n    algorithm = StringPrototypeToLowerCase(algorithm);\n\n    this.#digestType = algorithm;\n    try {\n      this.hash = createHash(this.#digestType);\n    } catch {\n      throw new Error(`Invalid digest: ${algorithm}`);\n    }\n  }\n\n  sign(\n    privateKey: any,\n    encoding?: any,\n  ): Buffer | string {\n    if (!privateKey) {\n      throw new ERR_CRYPTO_SIGN_KEY_REQUIRED();\n    }\n\n    const res = prepareAsymmetricKey(privateKey, kConsumePrivate);\n\n    // Options specific to RSA\n    const rsaPadding = getPadding(privateKey);\n\n    // Options specific to RSA-PSS\n    const pssSaltLength = getSaltLength(privateKey);\n\n    // Options specific to (EC)DSA\n    const dsaSigEnc = getDSASignatureEncoding(privateKey);\n\n    let handle;\n    if (ReflectHas(res, \"handle\")) {\n      handle = res.handle;\n    } else {\n      try {","sourceCodeStart":150,"sourceCodeEnd":186,"githubUrl":"https://github.com/denoland/deno/blob/9ad36f7a2cce60488e6ec52283efb32efddaf93a/ext/node/polyfills/internal/crypto/sig.ts#L150-L186","documentation":"Thrown by Sign.sign(privateKey) (the object returned by crypto.createSign(digest)) when the first argument is falsy. The Sign object only accumulates the data to be signed; the private key must be supplied at sign() time as a KeyObject, PEM string, or an options object such as { key, passphrase }. This mirrors Node's ERR_CRYPTO_SIGN_KEY_REQUIRED behavior.","triggerScenarios":"crypto.createSign(\"sha256\").update(data).sign(undefined); sign.sign(null); sign.sign() with no arguments; key read from an env var or JSON config that was missing so the destructured variable is undefined.","commonSituations":"PRIVATE_KEY env var unset in a deploy environment; PEM file read failed silently and produced undefined; refactor renamed the key variable so an old name is passed; migration from one-shot crypto.sign() to the streaming API where the key argument was dropped.","solutions":["Pass the private key as the first argument to sign(): a KeyObject from createPrivateKey(), a PEM string, or { key, passphrase } for encrypted PEMs.","If the key comes from an env var or file, fail fast with a clear error when loading returns empty instead of forwarding undefined.","Materialize and validate the key once at startup with crypto.createPrivateKey(pem) so bad key material surfaces immediately."],"exampleFix":"// before\nconst signer = crypto.createSign(\"sha256\");\nsigner.update(payload);\nconst sig = signer.sign(process.env.PRIVATE_KEY); // env unset -> ERR_CRYPTO_SIGN_KEY_REQUIRED\n\n// after\nconst key = crypto.createPrivateKey(fs.readFileSync(\"private.pem\")); // fails loudly if the key is bad\nconst sig = crypto.createSign(\"sha256\").update(payload).sign(key);","handlingStrategy":"validation","validationCode":"const keyPem = fs.readFileSync(\"private.pem\", \"utf8\");\nif (!keyPem || !keyPem.includes(\"PRIVATE KEY\")) {\n  throw new Error(\"private.pem missing or not a private key\");\n}\nconst key = crypto.createPrivateKey(keyPem); // also validates the material\nconst sig = crypto.createSign(\"sha256\").update(data).sign(key);","typeGuard":"function isSignKeyInput(k) {\n  if (!k) return false;\n  if (typeof k === \"string\" || k instanceof crypto.KeyObject) return true;\n  return typeof k === \"object\" && (typeof k.key === \"string\" || k.key instanceof crypto.KeyObject);\n}","tryCatchPattern":"try {\n  sig = signer.sign(key);\n} catch (e) {\n  if (e?.code === \"ERR_CRYPTO_SIGN_KEY_REQUIRED\") {\n    throw new Error(\"Signing aborted: private key was not provided or failed to load\");\n  }\n  throw e;\n}","preventionTips":["Materialize keys once at startup with createPrivateKey so missing/bad material fails immediately, not at first signature.","Never pass env vars directly into sign() — read and validate them first.","For passphrase-protected PEMs pass { key, passphrase } and check both fields."],"tags":["crypto","signing","node-compat","key-management"],"backgroundTag":"missing-private-key","analyzedSha":"9ad36f7a2cce60488e6ec52283efb32efddaf93a","analyzedAt":"2026-08-20T13:07:44.778Z","schemaVersion":2},"datasetVersion":"2026-08-21T13:17:26.733Z"}