{"record":{"id":"66d8539895c348ca","repo":"nextauthjs/next-auth","slug":"no-matching-decryption-secret","errorCode":null,"errorMessage":"no matching decryption secret","messagePattern":"no matching decryption secret","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"packages/core/src/jwt.ts","lineNumber":100,"sourceCode":"  const { payload } = await jwtDecrypt(\n    token,\n    async ({ kid, enc }) => {\n      for (const secret of secrets) {\n        const encryptionSecret = await getDerivedEncryptionKey(\n          enc,\n          secret,\n          salt\n        )\n        if (kid === undefined) return encryptionSecret\n\n        const thumbprint = await calculateJwkThumbprint(\n          { kty: \"oct\", k: base64url.encode(encryptionSecret) },\n          `sha${encryptionSecret.byteLength << 3}` as Digest\n        )\n        if (kid === thumbprint) return encryptionSecret\n      }\n\n      throw new Error(\"no matching decryption secret\")\n    },\n    {\n      clockTolerance: 15,\n      keyManagementAlgorithms: [alg],\n      contentEncryptionAlgorithms: [enc, \"A256GCM\"],\n    }\n  )\n  return payload as Payload\n}\n\ntype GetTokenParamsBase = {\n  secret?: JWTDecodeParams[\"secret\"]\n  salt?: JWTDecodeParams[\"salt\"]\n}\n\nexport interface GetTokenParams<R extends boolean = false>\n  extends GetTokenParamsBase {\n  /** The request containing the JWT either in the cookies or in the `Authorization` header. */","sourceCodeStart":82,"sourceCodeEnd":118,"githubUrl":"https://github.com/nextauthjs/next-auth/blob/a1a16a5a7780488c7449feece410033f445d0b31/packages/core/src/jwt.ts#L82-L118","documentation":"decode() in the Auth.js core tries each configured encryption secret to decrypt a JWE. It derives a thumbprint per secret and compares kid; if no secret matches, it throws 'no matching decryption secret'. This happens when the token was encrypted with a different secret than the ones currently configured.","triggerScenarios":"AUTH_SECRET/NEXTAUTH_SECRET changed or rotated after tokens were issued; multiple secrets configured but none matches the token's kid; token encrypted with a different alg/enc than allowed (keyManagementAlgorithms/contentEncryptionAlgorithms); decoding a token from another environment (staging vs prod).","commonSituations":"Deployments where the secret env var differs between build and runtime; secret rotation invalidating active sessions; sharing tokens across services with different secrets; debugging getToken() on tokens minted before a secret change.","solutions":["Set the same AUTH_SECRET (or `secret` option) that was used to encrypt the token","If rotating, include the old secret(s) in the `secret` array so existing tokens still decrypt — new tokens use the first","Confirm the token's kid/alg/enc match the adapter configuration (default dir/dir + A256GCM)","Re-issue the token/session if the original secret is unrecoverable (users must sign in again)"],"exampleFix":"// before\njwtDecode({ token, secret: process.env.NEW_SECRET })\n// after\njwtDecode({\n  token,\n  secret: [process.env.NEW_SECRET, process.env.OLD_SECRET], // old secret keeps existing tokens working\n})","handlingStrategy":"fallback","validationCode":"if (!process.env.AUTH_SECRET) throw new Error('AUTH_SECRET missing — tokens cannot be decrypted')","typeGuard":null,"tryCatchPattern":"try {\n  return await decode({ token, secret, ...params })\n} catch (e) {\n  if (e.message === 'no matching decryption secret') {\n    // secret mismatch/rotation — force re-authentication\n    return null\n  }\n  throw e\n}","preventionTips":["Keep AUTH_SECRET identical across environments and stable across deploys","On rotation, supply old secrets alongside the new one in the `secret` array","Never share tokens across services with different secrets","Treat this error as 'session invalid' and require sign-in"],"tags":["jwt","encryption","secret","session"],"backgroundTag":"jwt-decryption-secret-mismatch","analyzedSha":"a1a16a5a7780488c7449feece410033f445d0b31","analyzedAt":"2026-08-28T21:52:38.200Z","schemaVersion":2},"datasetVersion":"2026-08-29T02:17:18.158Z"}