{"record":{"id":"bba71756f18cf8bc","repo":"nextauthjs/next-auth","slug":"invalid-jwt","errorCode":null,"errorMessage":"Invalid JWT","messagePattern":"Invalid JWT","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"packages/core/src/lib/actions/session.ts","lineNumber":47,"sourceCode":"      ...(!isUpdate && {\n        \"Cache-Control\": \"private, no-cache, no-store\",\n        Expires: \"0\",\n        Pragma: \"no-cache\",\n      }),\n    },\n    cookies,\n  }\n\n  const sessionToken = sessionStore.value\n\n  if (!sessionToken) return response\n\n  if (sessionStrategy === \"jwt\") {\n    try {\n      const salt = options.cookies.sessionToken.name\n      const payload = await jwt.decode({ ...jwt, token: sessionToken, salt })\n\n      if (!payload) throw new Error(\"Invalid JWT\")\n\n      // @ts-expect-error\n      const token = await callbacks.jwt({\n        token: payload,\n        ...(isUpdate && { trigger: \"update\" }),\n        session: newSession,\n      })\n\n      const newExpires = fromDate(sessionMaxAge)\n\n      if (token !== null) {\n        // By default, only exposes a limited subset of information to the client\n        // as needed for presentation purposes (e.g. \"you are logged in as...\").\n        const session = {\n          user: { name: token.name, email: token.email, image: token.picture },\n          expires: newExpires.toISOString(),\n        }\n        // @ts-expect-error","sourceCodeStart":29,"sourceCodeEnd":65,"githubUrl":"https://github.com/nextauthjs/next-auth/blob/a1a16a5a7780488c7449feece410033f445d0b31/packages/core/src/lib/actions/session.ts#L29-L65","documentation":"When the session strategy is 'jwt', Auth.js decodes the session token cookie using jose with the configured secret and cookie name as salt. If decoding returns no payload (malformed, tampered, or undecryptable token), it throws 'Invalid JWT', which aborts session retrieval.","triggerScenarios":"The sessionToken cookie exists but its payload cannot be decoded: cookie encrypted/signed with a different AUTH_SECRET, token from another deployment/environment, manually crafted cookie value, or a token corrupted by truncation.","commonSituations":"Changing or losing NEXTAUTH_SECRET/AUTH_SECRET between deploys while users hold old cookies; running multiple instances with different secrets; switching between next-auth v4 and Auth.js v5 (different token formats); copying session cookies between localhost and production.","solutions":["Ensure AUTH_SECRET/NEXTAUTH_SECRET is set to the same stable value across all environments and instances sharing session cookies","Log the user out (delete the session cookie) so a fresh token is issued on next sign-in — old invalid cookies cannot be recovered","If migrating next-auth v4 to v5, expect old JWT cookies to be invalid and force re-authentication, or keep the legacy secret during a transition window","Confirm you are not mixing 'database' and 'jwt' strategies with cookies written by the other mode","Verify no middleware or proxy rewrites/truncates the session cookie (large cookies can be split or dropped)"],"exampleFix":"// before\n// no secret pinned; each deploy generates a new one\n// after\nexport const { handlers, auth, signIn, signOut } = NextAuth({\n  secret: process.env.AUTH_SECRET, // stable across deployments\n  session: { strategy: 'jwt' },\n});","handlingStrategy":"try-catch","validationCode":"function isSessionCookieShaped(v: string | undefined): boolean {\n  return !!v && v.split('.').length >= 2 && v.length > 20; // JWE/JWT-like shape\n}","typeGuard":"function hasPayload(p: unknown): p is Record<string, unknown> {\n  return typeof p === 'object' && p !== null && 'sub' in (p as object);\n}","tryCatchPattern":"try {\n  const session = await auth();\n} catch (e) {\n  if (/Invalid JWT/.test(String(e))) {\n    // clear the stale session cookie and redirect to sign-in\n    await signOut({ redirect: false });\n  }\n}","preventionTips":["Pin AUTH_SECRET/NEXTAUTH_SECRET in env, identical across all instances and deploys","Force re-login after major version migrations (v4 to v5 changes token format)","Do not mix 'database' and 'jwt' session strategies on the same cookies","Monitor for cookie-stripping middleware/proxies truncating large session cookies"],"tags":["jwt","session","configuration","authentication"],"backgroundTag":"invalid-jwt-token","analyzedSha":"a1a16a5a7780488c7449feece410033f445d0b31","analyzedAt":"2026-08-28T21:52:38.200Z","schemaVersion":2},"datasetVersion":"2026-08-29T02:17:18.158Z"}