# next-auth JWT session decryption failed after secret rotation

## TL;DR

The NEXTAUTH_SECRET rotated and existing JWTs were encrypted with the old one, so every session fails decryption. Support both secrets during rotation (decrypt with old, encrypt with new), then retire the old. Rotating a session secret without overlap logs everyone out.

```text
next-auth: JWT session decryption failed (after secret rotation)
```

## Steps

1. Confirm the timing: decryption failures start at the rotation.
   Expected: The cause is the new secret.

2. Add the old secret as a decryption fallback while issuing new tokens with the new secret.
   Expected: Old sessions decrypt again.

3. Let sessions naturally roll over to the new secret as they refresh.
   Expected: The old-secret population drains.

4. Remove the fallback after the max session lifetime passes.
   Expected: Only the new secret remains.

5. Document the overlap procedure for the next rotation.
   Expected: Rotations stop logging everyone out.

## When to use

- next-auth sessions die after a secret rotation
- JWT decryption errors appear
- the secret recently changed

## When not to use

- the secret did not change (check for corruption instead)
- using database sessions (different storage, different failure)
- the error is on token creation, not decryption (check the new secret's validity)

## Tool compatibility

- next-auth / Auth.js
- JWT sessions

## Variant phrasings

- "next-auth JWT decryption failed"
- "nextauth secret rotation sessions"
- "JWT session decryption failed secret"

## Why it happens

JWT sessions are encrypted with the secret; rotation invalidates every outstanding token instantly. Without an overlap window, the rotation is a mass logout. The decrypt-with-old/encrypt-with-new pattern is the standard fix, and it needs to be planned before the rotation, not after.

## Edge cases

- the overlap window must cover the max session lifetime, or long sessions still die
- the old secret must be retired, not kept forever; schedule its removal
- this applies to any JWT session secret, not just next-auth

## Provenance

Resolved from the public thread: https://vectle.com/posts/pst_BlCiVGvtUC5XrcWEsH5z3g
