Single failed proactive token refresh hard-wipes auth and traps every session in an uncompletable /login
A single failed proactive token refresh hard-wipes auth and traps every session in an uncompletable /login
Environment
- Claude Code: 2.1.195 (npm-global,
@anthropic-ai/claude-code) - OS: macOS (Darwin 25.5.0), Apple Silicon
- Auth: claude.ai subscription (OAuth), no
ANTHROPIC_API_KEY - Credential store: macOS Keychain (
Claude Code-credentials) - Multiple concurrent Claude Code clients on one machine sharing the single OAuth credential: the desktop app, the headless
claude.exe daemon, several background/forked sessions, and terminalclaude.
Summary
After ~2 weeks of flawless automatic token refreshes, one scheduled proactive refresh failed. Instead of falling back to the still-valid keychain token, the daemon discarded the token entirely (no token found), and from that instant every session — including brand-new ones — demanded /login. The /login flow is itself unusable in the TUI, so there was no in-TUI way to recover.
There are really two bugs here:
Bug 1 — one failed proactive refresh hard-discards auth for all sessions
From ~/.claude/daemon.log, the refresh ran cleanly every ~8h for two weeks, then failed exactly once and nuked the token:
[2026-06-14T19:59:16Z] [supervisor] auth: proactive refresh succeeded
... (≈30 consecutive successes, every ~8h, through Jun 27) ...
[2026-06-27T02:32:31Z] [supervisor] auth: proactive refresh succeeded <- last good
[2026-06-28T02:18:54.730Z] [supervisor] auth: proactive refresh starting
[2026-06-28T02:18:54.786Z] [supervisor] auth: proactive refresh failed, signalling re-auth required
[2026-06-28T02:18:54.791Z] [supervisor] auth: headless daemon cannot complete OAuth — run `claude auth login` to refresh
[2026-06-28T02:18:54.791Z] [supervisor] auth: no token found, will re-check keychain every 30s
Every /login prompt across all sessions dates from that 02:18:54Z event. A single transient/revoked refresh should not wipe auth and lock all sessions — it should fall back to the unexpired keychain access token and/or retry, not declare no token found.
Likely trigger: the refresh token was revoked server-side. This lines up with a Pro→Max subscription upgrade (and/or signing in again on web/desktop) shortly before — changing subscription appears to revoke existing OAuth refresh tokens, so the daemon's next routine refresh failed. Earlier log lines also show multiple processes refreshing the same credential cross-process (token still valid (cross-process refresh or not yet due)), so shared-credential rotation may compound this.
Bug 2 — the TUI /login flow is unusable, so there is no recovery path inside the TUI
When dropped into /login:
- The login URL does not auto-open a browser, even though
$BROWSERis empty (so it should fall back toopen) andopen https://anthropic.comworks fine from the same shell. - The
c"copy URL" shortcut does not place the URL on the clipboard (nothing copied). - The full-screen TUI has mouse reporting on, so normal click-drag selection of the URL is swallowed by the app — can't manually select + ⌘C either.
Net effect: the URL is visible on screen but there is no working path to follow it, so login cannot be completed from within the TUI. (Workaround that does work: claude auth login as a plain CLI command outside the TUI.)
Symptoms observed
- New, post-upgrade sessions: typing any message returns
Not logged in · Please run /login. claude auth statussimultaneously reports{ "loggedIn": true, "subscriptionType": "max" }and the keychain holds a non-expired access token — i.e. a valid token exists, yet inference is rejected and the daemon reportsno token found.- Resuming any session that was open across the 02:18 event always re-throws
/loginand can never be revived for sending (its content is still readable on disk).
Steps to reproduce
- Run Claude Code (subscription/OAuth) with the background daemon and one or more other clients (desktop app, extra CLI sessions) sharing the keychain credential.
- Change the subscription tier (e.g. Pro→Max) and/or sign in again on another Claude surface, revoking the existing refresh token.
- Wait for the daemon's next scheduled proactive refresh.
- Observe: refresh fails →
no token found→ all sessions (including new ones) demand/login. - In the TUI
/login: the URL neither auto-opens nor copies; login cannot be completed.
Expected
- A failed proactive refresh should retry and/or fall back to the still-valid keychain access token, not discard auth for every session.
- A subscription change should not silently brick existing CLI sessions; if the refresh token is revoked, re-auth should be needed once and recover cleanly, not trap sessions.
- The TUI
/loginURL must be openable (honoropen/$BROWSER) and copyable; with mouse reporting on, provide a reliable copy affordance.
Actual
All sessions stuck on /login with a valid token present; the TUI /login is a dead end; the only recovery was claude auth logout && claude auth login from a plain shell. Sessions that were live across the event are permanently unresumable for sending.
Workaround
claude auth logout
claude auth login --claudeai # plain CLI; URL prints as normal text and auto-opens via `open`
claude auth status # confirm loggedIn:true + correct subscriptionType
Then fully quit lingering clients (incl. the headless claude.exe daemon, which respawns) so they re-read the fresh keychain token; start a new session (old ones remain unresumable).
This issue has 2 comments on GitHub. Read the full discussion on GitHub ↗