{"record":{"id":"032ac340858c2605","repo":"vercel/ai","slug":"continuation-signing-key-must-not-be-empty","errorCode":null,"errorMessage":"Continuation signing key must not be empty.","messagePattern":"Continuation signing key must not be empty\\.","errorType":"validation","errorClass":"TypeError","httpStatus":null,"severity":"error","filePath":"packages/code-mode/src/continuation-capability.ts","lineNumber":43,"sourceCode":"  const resolved = resolveCodeModeContinuationSecurity({\n    signingKey: key ?? randomBytes(32),\n    maxAgeMs: options.maxAgeMs ?? DEFAULT_MAX_AGE_MS,\n  });\n  defaultSigningKey = resolved.signingKey;\n  defaultMaxAgeMs = resolved.maxAgeMs;\n}\n\nexport function resolveCodeModeContinuationSecurity(\n  options: CodeModeContinuationSecurityOptions = {},\n): ResolvedCodeModeContinuationSecurity {\n  const signingKey =\n    options.signingKey === undefined\n      ? Buffer.from(defaultSigningKey)\n      : typeof options.signingKey === 'string'\n        ? Buffer.from(options.signingKey)\n        : Buffer.from(options.signingKey);\n  if (signingKey.byteLength === 0) {\n    throw new TypeError('Continuation signing key must not be empty.');\n  }\n\n  const maxAgeMs = options.maxAgeMs ?? defaultMaxAgeMs;\n  if (\n    !Number.isInteger(maxAgeMs) ||\n    !Number.isFinite(maxAgeMs) ||\n    maxAgeMs <= 0\n  ) {\n    throw new TypeError('Continuation maxAgeMs must be a positive integer.');\n  }\n\n  return { signingKey, maxAgeMs };\n}\n\nexport function signCodeModeContinuation(\n  continuation: UnsignedCodeModeContinuation,\n  security = resolveCodeModeContinuationSecurity(),\n): CodeModeContinuation {","sourceCodeStart":25,"sourceCodeEnd":61,"githubUrl":"https://github.com/vercel/ai/blob/69428b1f8b037e4d118fb4853428d5c4e620493c/packages/code-mode/src/continuation-capability.ts#L25-L61","documentation":"resolveCodeModeContinuationSecurity converts the configured signing key into a Buffer and throws a TypeError if the resulting key has zero bytes. The key signs HMAC-SHA256 continuation tokens, and an empty key would make signatures trivially forgeable, so the library refuses it outright. It is thrown when calling setCodeModeContinuationSigningKey, signCodeModeContinuation, or verifyCodeModeContinuation with an empty key.","triggerScenarios":"Calling setCodeModeContinuationSigningKey('') or new Uint8Array(0); passing a signingKey option resolved from an env var that is undefined and defaulted to '' (e.g. process.env.KEY ?? ''); passing a zero-length Buffer; a key string that is empty after upstream trimming or secret-manager lookup returning an empty value.","commonSituations":"Missing CONTINUATION_SIGNING_KEY environment variable silently defaulted to empty string; config loader stripping values; storing the key in a secret manager that returned empty during startup; copying code with placeholder key '' left in place.","solutions":["Set the signing key to a non-empty value, e.g. setCodeModeContinuationSigningKey(process.env.CONTINUATION_SIGNING_KEY)","Fail fast at startup: read the env var and throw your own clear error if it is missing or empty before calling the API","Generate a strong key if none exists, e.g. call setCodeModeContinuationSigningKey() with no argument to use randomBytes(32)","Verify the upstream secret source actually returned a value (check secret name/region/permissions)"],"exampleFix":"// before\nconst key = process.env.CONTINUATION_SIGNING_KEY ?? '';\nsetCodeModeContinuationSigningKey(key); // TypeError: must not be empty\n// after\nconst key = process.env.CONTINUATION_SIGNING_KEY;\nif (!key || key.length === 0) {\n  throw new Error('CONTINUATION_SIGNING_KEY is required');\n}\nsetCodeModeContinuationSigningKey(key);","handlingStrategy":"validation","validationCode":"const key = process.env.CONTINUATION_SIGNING_KEY;\nif (typeof key !== 'string' || key.length === 0) {\n  throw new Error('CONTINUATION_SIGNING_KEY must be a non-empty string');\n}\nsetCodeModeContinuationSigningKey(key);","typeGuard":"function hasNonEmptyKey(k: string | Uint8Array | undefined): k is string | Uint8Array {\n  if (k === undefined) return false;\n  return (typeof k === 'string' ? k.length : k.byteLength) > 0;\n}","tryCatchPattern":"try {\n  setCodeModeContinuationSigningKey(key);\n} catch (error) {\n  if (error instanceof TypeError && /signing key must not be empty/.test(error.message)) {\n    throw new Error('Refusing to start: continuation signing key is empty. Check CONTINUATION_SIGNING_KEY.');\n  }\n  throw error;\n}","preventionTips":["Validate signing-key env vars at process startup with fail-fast checks","Never default key config to empty string; default to throwing instead","Call setCodeModeContinuationSigningKey() with no args (random key) in dev/test","Audit secret-manager lookups for empty returns (wrong secret name/region)"],"tags":["configuration","security","hmac","empty-key"],"backgroundTag":"missing-env-var","analyzedSha":"69428b1f8b037e4d118fb4853428d5c4e620493c","analyzedAt":"2026-08-30T12:32:21.016Z","schemaVersion":2},"datasetVersion":"2026-08-30T13:17:10.514Z"}