Multiple CLI sessions race on ~/.claude/.credentials.json token refresh

Resolved 💬 3 comments Opened May 5, 2026 by emmacoleiq Closed May 8, 2026

Summary

When multiple Claude Code CLI sessions run concurrently, they share ~/.claude/.credentials.json for OAuth token storage with no file-level locking. When one session refreshes its access token (writing new access + refresh tokens to the file), other sessions holding the old tokens in memory get 401s. Their subsequent refresh attempts may fail if the server rotates refresh tokens, causing a cascading "logged out" state across sessions.

Reproduction

  1. Open 3-4 terminal tabs, each running claude in different project directories
  2. Wait for any session's access token to approach expiry (or trigger a refresh)
  3. One session refreshes successfully and writes new tokens to .credentials.json
  4. Other sessions get 401, attempt refresh with the now-stale refresh token
  5. Those sessions report "logged out" and prompt for /login
  6. Running /login in one session invalidates the tokens the first session just wrote
  7. Cascade continues

Environment

  • Claude Code 2.1.116
  • macOS (Darwin 25.4.0, arm64)
  • 4 concurrent CLI sessions + Desktop app (separate token store)
  • Claude Max subscription

Expected Behavior

Multiple concurrent CLI sessions should be able to share credentials without racing. Options:

  • File-level locking (flock/fcntl) around read-modify-write of .credentials.json
  • Per-session token storage with a shared refresh coordinator
  • Re-read the file before refreshing to check if another session already refreshed
  • IPC-based token refresh coordination (only one session refreshes, others wait)

Additional Context

The problem is amplified when other tools (e.g., credential managers) also do read-modify-write operations on the same file for MCP OAuth tokens stored in the mcpOAuth key. The lack of file locking means any concurrent writer can roll back another's token update.

🤖 Generated with Claude Code

View original on GitHub ↗

This issue has 3 comments on GitHub. Read the full discussion on GitHub ↗