OAuth refresh token rejected server-side after ~24h - forced /login every day (Max sub, single machine)

Status Open
Maintainer reply None cached
Activity 3 comments · opened Jul 16, 2026

Environment

  • Claude Code v2.1.198, Windows 11 Pro (10.0.26200), native install
  • Max subscription (rateLimitTier: default_claude_max_5x)
  • Single machine, no WSL/remote/second device using the account

Bug

Since ~2026-07-14 I am forced to run /login every morning. The OAuth refresh token is rejected server-side after ~24h even though it is intact locally and never rotated.

Evidence (passive probe logging SHA256 fingerprints of .credentials.json, no secrets)

  • 2026-07-15 09:55:19 — /login, new refresh token (fp 643B3DD7282F), access token expiry 17:55.
  • All day 2026-07-15 (probe every 20 min): file untouched, same fingerprints. PC off overnight.
  • 2026-07-16 07:31 → 09:53 (pre-login): file still byte-identical (mtime unchanged, same length, same refreshFp). Nothing local modified or wiped the credentials.
  • 2026-07-16 09:55:10 — CLI forced /login; refresh token rejected. New fingerprints written.
  • Gap between logins: almost exactly 24h (09:55:19 → 09:55:10), suggesting a ~24h server-side refresh-token TTL or session invalidation.

Ruled out

  • Local file wipe/corruption (probe shows file byte-identical pre-login)
  • OneDrive/sync, scheduled tasks, second machine, Claude desktop app
  • Docker containers previously also logged into this account, but they have been idle for days and the daily forced login continues.

Expected

Refresh token silently renews the ~8h access token; login should persist for weeks.

Actual

Refresh token rejected after ~24h → daily forced /login.

View original on GitHub ↗

2 Comments

djdubd · 1 month ago

Independent data point that may help narrow this down: we run a background/automated Claude Code account (not an interactive daily-driver session — a dedicated CLAUDE_CONFIG_DIR used only by a small polling service, no manual /login in between) and have hit what looks like the same failure signature three times in the same window as this report: 2026-07-13, 2026-07-15, and 2026-07-16. Each time, a previously-working refresh token gets rejected and the local credentials file ends up with no usable access/refresh token, forcing an interactive re-login to recover. No local corruption or sync tooling involved on our end either — single isolated login, untouched between refresh attempts.

The ~24h-ish cadence and "locally intact, rejected server-side" shape matches what's described here closely enough that this seems more likely to be server-side than something specific to any one client setup.

meowmana · 13 days ago

Adding a data point from a different trigger, same root disease: refresh rotation is not crash-safe.

Headless VPS, Max subscription, a user:profile-scoped credential used only for polling the usage endpoint. During a scheduled refresh the server invalidated the old refresh token and issued a new one, but the machine was under heavy load and the process died before the new token hit disk. Old token: already revoked. New token: never persisted. → permanent invalid_grant, manual browser re-auth as the only way out.

Rotation that invalidates the old secret before the client confirms persistence of the new one turns every crash, OOM-kill or power loss into a forced re-login. Either the old refresh token needs a grace window until first use of the new one, or refresh tokens shouldn't rotate on every exchange. On top of that, forced monthly re-auth for long-lived headless setups makes this a recurring operational burden, not a one-off.

Showing cached comments. Read the full discussion on GitHub ↗