[BUG] Auth session invalidated after sleep on macOS 26: background token refresh corrupts keychain credential instead of retaining old token
Preflight Checklist
- [x] I have searched existing issues and this hasn't been reported yet
- [x] This is a single bug report (please file separate reports for different bugs)
- [x] I am using the latest version of Claude Code
What's Wrong?
claude auth status --text intermittently reports "Not logged in" throughout the day — including during active use, not just after overnight sleep. Re-running claude auth login restores the session temporarily. Did not occur on the same account on an older macOS version.
What Should Happen?
Session should not be destroyed that I can continue using Claude without the need to re-authenticate.
When a background token refresh fails, Claude Code should retain the existing credential and retry, not invalidate the stored session.
Error Messages/Logs
security find-generic-password -s "Claude Code-credentials" 2>/dev/null | grep "mdat\|cdat
"cdat" = "20260626092437Z" ← last login
"mdat" = "20260627043751Z" ← credential overwritten during failed refresh → session dead
Steps to Reproduce
- Use Claude during the day.
- Notice that after some time, the system asks if using the stored entry in the Keychain Access is fine. Even by clicking
Always Allow, it asks again.
Sorry, no clear steps to reproduce are available.
Claude Model
None
Is this a regression?
I don't know
Last Working Version
_No response_
Claude Code Version
2.1.181
Platform
Anthropic API
Operating System
macOS
Terminal/Shell
iTerm2
Additional Information
The keychain entry (Claude Code-credentials) is not deleted — it still exists after the session dies. Its mdat timestamp is updated at the time the session becomes invalid, indicating Claude Code's background token refresh ran, failed, and wrote back an invalid state to the keychain instead of retaining the previously valid credential.
4 Comments
Corroborating evidence from a separate macOS machine (Claude Code 2.1.195, Apple Silicon), which I filed as #72006 and am closing as a duplicate of this.
The background daemon's own auth log (
~/.claude/daemon.log) shows the exact failure mode you describe — a failed proactive refresh discards the credential instead of retaining the still-valid token:Every
/loginprompt across all sessions dates from that single 02:18:54Z event. A single failed refresh shouldn't transition the daemon tono token found— it should fall back to the unexpired keychain access token and retry.Two additional data points that may refine the root cause beyond "after sleep":
auth: token still valid (cross-process refresh or not yet due)) — i.e. multiple concurrent Claude Code clients (desktop app, headlessclaude.exe daemon, background/forked sessions, terminal CLI) share the one keychain credential and rotate it. That shared-credential rotation looks like it can leave one client holding a refresh token that's already been rotated away, so its next refresh fails.Symptom contradiction worth noting: at the same time,
claude auth statusreported{"loggedIn": true, "subscriptionType": "max"}and the keychain held a non-expired access token, yet inference returnedNot logged inand the daemon reportedno token found.Follow-up from the same machine (Claude Code 2.1.195, macOS) — the recovery path is also broken, not just the initial wipe.
After the failed proactive refresh put the daemon into:
…doing exactly what it asks —
claude auth login— did not recover the running daemon:claude auth status→loggedIn: true, correct subscription;security find-generic-passwordshows a validexpiresAt).no token foundstate. Its advertised "re-check keychain every 30s" self-heal never picked up the new token —daemon.logshows no furtherauth:lines after the failure, and brand-new TUI sessions kept showing/loginbecause they reuse that daemon.claude.exe daemon runsupervisor is a separate background process and survives).pkill -f 'claude.exe daemon run'left it running (same PID). Only SIGKILL (kill -9/pkill -9) stopped it; after that, a freshclaudespawned a new daemon that read the valid keychain token and logged in normally.So the effective workaround is two steps, not one:
Suggested fixes: (1) the
every 30skeychain re-check should actually re-load and clear theno token foundstate when a valid credential reappears; (2) the supervisor should honor SIGTERM so a normalpkill/shutdown works; (3) ideally a failed refresh shouldn't drop the daemon into a state that a successful re-auth can't recover without a manual kill.I had ~60 orphaned
Claude Code-credentials-<hash>entries in my macOS keychain, and no plainClaude Code-credentialsentry existed until I deleted everything and did a fresh OAuth login.Try to check if it is a DNS pollution issue.