2.1.138 OAuth refresh storm

Resolved 💬 3 comments Opened May 11, 2026 by DonQuilatte Closed May 15, 2026

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?

N concurrent sessions (CLI+VSCode×N) mutually revoke access tokens every ~5min. When two or more Claude Code processes run concurrently against the same OAuth credential (e.g., CLI in terminal plus one or more VSCode extension sessions), each process refreshes the access token in the macOS Keychain on roughly a 5-minute cadence. Each refresh appears to revoke any previously issued access token server-side, so sibling processes immediately receive 401 Invalid authentication credentials and the VSCode extension UI flips to "logged out." Users have to re-authenticate, and the cycle repeats.

What Should Happen?

Running multiple Claude Code sessions concurrently against a single OAuth credential is a documented, supported workflow (CLI alongside VSCode extension, multiple VSCode workspaces, etc.). Expected:

  1. No proactive refresh while the access token is still valid. The keychain entry's expiresAt (claudeAiOauth.expiresAt) sits ~5 days in the future. The CLI should only refresh when the token is within a small grace window of expiry (e.g., < 5 minutes remaining), not every 5 minutes against a 5-day-old token.
  2. Refreshed access tokens should not invalidate previously issued tokens until the prior token's own expiry. If the OAuth server is currently issuing single-use access tokens that revoke siblings on every refresh, this is incompatible with the multi-process model the client supports.
  3. Cross-process coordination on refresh. If a refresh is genuinely needed, the first process should acquire a lock (the client already uses ~/.claude/locks/), perform the refresh once, and other processes should re-read the keychain instead of independently initiating their own refresh.
  4. Stable session UI. With (1)–(3) in place, all concurrent sessions remain authenticated continuously. No 401s, no "logged out" UI flips, no manual claude logout && claude login cycles.

Error Messages/Logs

Steps to Reproduce

Watch loop output (one-minute granularity), with one terminal CLI session and one VSCode extension session active:
15:10:57 mdat=20260511151057Z
15:16:27 mdat=20260511151627Z ← +5m 30s, token rewritten
15:20:08 mdat=20260511152008Z ← +3m 41s, token rewritten again

Each mdat change correlates with a new accessToken value in the keychain blob, while expiresAt keeps advancing ~5 days into the future. During the same window, the VSCode extension flipped to its "sign in" UI twice and the CLI emitted 401 Invalid authentication credentials once on a routine tool call.
With six concurrent processes observed (one Claude desktop session + five VSCode extension --enable-auth-status sessions), the cycle compresses to ~1 refresh/minute and authentication is effectively unusable.

Repro

  1. Sign in to Claude Code on macOS via OAuth (Max subscription).
  2. Open two terminals; run claude in one and leave a VSCode workspace with the Claude extension panel active in the other.
  3. In a third terminal, watch the keychain:

```bash
while true; do
printf '%s ' "$(date +%T)"
security find-generic-password -s "Claude Code-credentials" -a "$USER" 2>&1 | grep mdat
sleep 30
done

Claude Model

Opus

Is this a regression?

Yes, this worked in a previous version

Last Working Version

_No response_

Claude Code Version

2.1.138

Platform

Anthropic API

Operating System

macOS

Terminal/Shell

Terminal.app (macOS)

Additional Information

_No response_

View original on GitHub ↗

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