OAuth session silently invalidated: client_data returns empty, repeated /login prompts
Bug Description
Claude Code CLI repeatedly prompts for /login after every interaction, even though the OAuth token in the keychain is unexpired. This has been happening for several days and is severely disruptive to workflows.
Root Cause Investigation
I traced the issue to the client_data API endpoint returning empty data:
GET https://api.anthropic.com/api/oauth/claude_cli/client_data
→ 200 {"client_data": {}}
The OAuth token is technically valid (gets a 200 response), but the underlying session is invalidated server-side. The organizations endpoint confirms this:
GET https://api.anthropic.com/api/organizations
→ 403 {"error": {"type": "permission_error", "message": "Invalid authorization", "details": {"error_code": "account_session_invalid"}}}
This causes the CLI to:
- Cache
hasAvailableSubscription: falsein~/.claude.json - Cache
clientDataCache.data: {}(empty) - Prompt for
/loginto re-authenticate - Fresh session works, then invalidates again within hours
Suspected Trigger
I frequently run multiple concurrent Claude Code sessions (2-3 processes) with parallel background agents. The token refresh code uses a file-lock mutex (proper-lockfile on the ~/.claude directory), but with multiple independent CLI processes, race conditions in the refresh flow may cause one process to invalidate another's session.
The decompiled refresh flow (QJq function) acquires a lock, checks if the token is still expired, then calls Kp_ to refresh. If two processes race past the expiry check before either acquires the lock, or if the Anthropic backend has a session concurrency limit, one refresh could invalidate the other's session.
Environment
- Claude Code version: 2.1.81
- Install method: native (macOS, arm64)
- Subscription: Max (stripe_subscription)
- OS: macOS Darwin 24.6.0
- Auth method: OAuth (claude.ai)
- Concurrent sessions: Typically 2-3 CLI processes with parallel background agents
Steps to Reproduce
- Run multiple concurrent Claude Code sessions (e.g., main session + background agents)
- Use sessions long enough for a token refresh cycle to occur
- After some time, one or more sessions will start showing "Not logged in" prompts
- Running
/loginfixes it temporarily, but the issue recurs
Expected Behavior
- OAuth token refresh should be safe across concurrent CLI processes
client_datashould never return empty{}for a valid, unexpired token- If a session is invalidated server-side, the refresh token should automatically recover without user intervention
Actual Behavior
- Sessions are silently invalidated server-side
client_datareturns200 {"client_data": {}}instead of an error, making it a silent failure- The CLI caches the empty response and prompts for
/login - This happens repeatedly, requiring manual
/loginafter nearly every interaction
This issue has 3 comments on GitHub. Read the full discussion on GitHub ↗