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

  1. Ensure all instances use the same stable AUTH_SECRET (set it explicitly in env, not generated per-instance).
  2. Complete sign-in flows across deploys; old in-flight sessions become invalid after a secret rotation — start the flow again.
  3. Inspect the cookie in devtools: if it's truncated or garbage, check proxy header limits and middleware interference.
  4. 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

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


AI-assisted analysis of nextauthjs/next-auth@a1a16a5a77 (2026-08-28). Data as JSON: /api/errors/142352c4cc88251f. Report an issue: GitHub.