nextauthjs/next-auth · error
Invalid cookie
Error message
Invalid cookie
What it means
parseCookie throws "Invalid cookie" when the check cookie exists but decoding it yields no `value` payload — i.e. the JWT-decoded cookie payload is empty or malformed. This is an internal consistency check after JWT decode with the configured secret and cookie-name salt.
Source
Thrown at packages/core/src/lib/actions/callback/oauth/checks.ts:74
return { name: cookie.name, value: encoded, options: cookieOptions }
}
async function parseCookie(
name: keyof CookiesOptions,
value: string | undefined,
options: InternalOptions
): Promise<string> {
try {
const { logger, cookies, jwt } = options
logger.debug(`PARSE_${name.toUpperCase()}`, { cookie: value })
if (!value) throw new InvalidCheck(`${name} cookie was missing`)
const parsed = await decode<CookiePayload>({
...jwt,
token: value,
salt: cookies[name].name,
})
if (!parsed?.value) throw new Error("Invalid cookie")
// The check must have been created by the provider currently handling
// the callback.
if (parsed.provider !== options.provider?.id) {
throw new Error(
`${name} cookie was created for a different provider than the one handling the callback`
)
}
return parsed.value
} catch (error) {
throw new InvalidCheck(`${name} value could not be parsed`, {
cause: error,
})
}
}
function clearCookie(
name: keyof CookiesOptions,
options: InternalOptions,View on GitHub (pinned to a1a16a5a77)
Solutions
- Ensure all instances use the same stable AUTH_SECRET (set it explicitly in env, not generated per-instance).
- Complete sign-in flows across deploys; old in-flight sessions become invalid after a secret rotation — start the flow again.
- Inspect the cookie in devtools: if it's truncated or garbage, check proxy header limits and middleware interference.
- Restart the sign-in flow to get a fresh cookie set.
Example fix
// before: random secret per instance breaks decode
const secret = crypto.randomBytes(32).toString("hex")
// after: shared stable secret
export const { handlers } = NextAuth({
secret: process.env.AUTH_SECRET,
providers: [],
}) Defensive patterns
Strategy: try-catch
Validate before calling
if (!process.env.AUTH_SECRET) {
throw new Error("AUTH_SECRET must be set explicitly and shared by all instances")
} Type guard
function isCookiePayload(v: unknown): v is { value: string; provider?: string } {
return typeof v === "object" && v !== null && "value" in v
} Try / catch
try {
await auth()
} catch (e) {
if (e?.message?.includes("Invalid cookie")) {
// secret mismatch or corrupted cookie: force a new sign-in
}
} Prevention
- Set one fixed AUTH_SECRET across all servers and environments
- Expect in-flight sign-ins to break after secret rotation and have users retry
- Check middleware/proxies for cookie truncation or rewriting
When it happens
Trigger: Cookie value present at callback but decode() returns null/undefined or an object without `value`, typically because the cookie was tampered with, encrypted with a different AUTH_SECRET, or truncated/truncated by a proxy with header size limits.
Common situations: AUTH_SECRET changed between sign-in start and callback (deploy mid-flow, multiple instances with different secrets); load balancer sending the callback to a server with a different secret; cookie mangled by middleware rewriting headers.
Related errors
- ${name} value could not be parsed
- ${name} cookie was missing
- ${name} cookie was created for a different provider than the
- Invalid state
- Account not created
AI-assisted analysis of nextauthjs/next-auth@a1a16a5a77 (2026-08-28).
Data as JSON: /api/errors/142352c4cc88251f.
Report an issue: GitHub.