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 (fp643B3DD7282F), 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 (
mtimeunchanged, same length, samerefreshFp). 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.
Showing cached comments. Read the full discussion on GitHub ↗
2 Comments
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_DIRused only by a small polling service, no manual/loginin 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.
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. → permanentinvalid_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.