OAuth credentials silently wiped on failed token refresh — long-running agents lose auth
Description
Long-running Claude Code agents (persistent tmux sessions that run 24/7) are losing their OAuth authentication every ~12 hours. On restart, the session shows "Not logged in" even though the keychain entry Claude Code-credentials exists.
Root cause investigation
On the affected machine (macOS, Claude Code 2.1.63):
- The
Claude Code-credentialskeychain entry exists but contains empty data - The entry's
cdat(creation date) shows it was recreated today — suggesting the original valid credential was deleted and replaced with an empty one - The keychain is set to
no-timeoutand was confirmed unlocked at the time - The machine does not sleep (
pmset sleep = 0)
Theory: When the OAuth token expires, Claude Code attempts a refresh. If the refresh fails (network blip, server error, etc.), the old credential is deleted/overwritten with an empty value instead of being preserved. This leaves the agent in a state where:
- The keychain entry exists (so no "missing credential" error)
- But the entry is empty (so auth fails silently)
- The only recovery is a full manual re-login via browser OAuth flow
Expected behavior
- If a token refresh fails, the existing valid credential should be preserved (not overwritten with empty data)
- If the credential becomes invalid, a clear error message should be logged (not silent failure)
- Ideally, Claude Code should retry the refresh before giving up
Environment
- Claude Code version: 2.1.63
- OS: macOS (Darwin 25.2.0) on Mac Mini
- Auth method: OAuth (browser flow via
/login) - Usage pattern: Persistent tmux session, watchdog auto-restart, running 24/7
- 3 agents on 3 separate machines all running the same version — issue observed on one so far
Impact
For autonomous agents that run unattended, this is a hard failure that requires human intervention (browser OAuth flow). It's particularly disruptive because:
- The agent appears to start normally but can't make any API calls
- No error is logged until the agent tries to do work
- The human may not notice for hours
Workaround
Currently: human manually completes the /login OAuth flow when detected.
Suggested: store an API key as a fallback auth method so the agent can self-recover when OAuth expires.
This issue has 3 comments on GitHub. Read the full discussion on GitHub ↗