[BUG] Windows: recurring forced logouts since ~Jul 22 — .credentials.json overwritten with test-fixture content ("fixture-claude-secret-value-x")
Bug: Windows — recurring forced logouts since ~Jul 22; .credentials.json found overwritten with test-fixture content
Preflight
- [x] Searched existing issues. Related but distinct: #80585 (macOS Keychain, concurrent-session refresh race), #80292 (multi-device ping-pong), #80085 (macOS keychain concurrency), #81512 (Cowork server-side session TTL). None cover Windows, and none report the fixture-content overwrite below.
- [x] Single bug report.
- [x] Latest version (CLI 2.1.220).
Environment
- OS: Windows 11 Pro 10.0.26200
- Claude Code CLI: 2.1.220, native installer (
~/.local/bin/claude.exe, versions dir~/.local/share/claude/versions/) - Claude Desktop app: 1.24012.9 (MSIX,
WindowsApps), which runs its own embedded CLI 2.1.219 (%APPDATA%\Claude\claude-code\2.1.219\claude.exe) - Auth: subscription OAuth, stored in
~/.claude/.credentials.json(no keychain on Windows) - Workflow: several concurrent long-lived sessions is normal here — at capture time 4 standalone CLI sessions (
--dangerously-skip-permissions, one alive since Jul 25 12:29) plus the desktop app's embedded CLI, all sharing the single~/.claude/.credentials.json
Symptom
Since ~Jul 22, active sessions are forced to /login one to three times per day. The active session prints Not logged in · Please run /login mid-turn (in the latest case, seconds after a successful Write tool call) and all other concurrent sessions are logged out at the same time.
Logout banner occurrences found in session transcripts (timestamp = last entry in each affected session, UTC):
2026-07-22T11:17Z, 2026-07-24T19:44Z, 2026-07-25T12:15Z, 2026-07-25T16:30Z,
2026-07-25T18:40Z, 2026-07-25T22:48Z (background agent), 2026-07-26T09:50Z,
2026-07-26T18:19Z, 2026-07-27T08:07Z
Nine forced logouts in six days. Before Jul 22 there are zero occurrences in the transcript history, so this began with the 2.1.216/2.1.217-era releases — the same window as #80292 / #80585 / #80085 on macOS.
The unusual part: what the credentials file contained after the logout
Five seconds after the Jul 27 logout banner (transcript timestamp 08:07:06Z; file mtime 08:07:11Z), ~/.claude/.credentials.json was 42 bytes containing test-fixture data, not a cleared or real credential:
{"token": "fixture-claude-secret-value-x"}
That is not the production schema (claudeAiOauth / accessToken / refreshToken / expiresAt) — it looks like a unit-test fixture.
I searched exhaustively for the origin of that string on the machine. It does not exist anywhere except the credentials file itself:
- not in any project repo (including gitignored files), any Python venv, or any test suite on disk
- not in
~/.claude(plugins, hooks, transcripts, file-history, settings) — and Claude Code's own file-history confirms no agent session wrote the file - not in the CLI binaries for 2.1.218 / 2.1.219 / 2.1.220
- not in the desktop app 1.24012.9 (
app.asar,app.asar.unpacked,claude.exe,cowork-svc.exe,chrome-native-host.exe,ion-dist) - no hooks are configured globally, and the only project PreToolUse hook is read-only
So whatever wrote it either constructs the string at runtime or it arrived from the network and was persisted verbatim.
Hypotheses
- Refresh-rotation race (Windows variant of #80585): concurrent sessions share the single
.credentials.json; refresh tokens are single-use; the loser of the rotation race gets aninvalid_grant-class failure and the credential is clobbered, logging out every session. The Jul-22 start date and multi-session workflow match #80585/#80292 exactly — Windows just has no keychain, so the shared file is even more exposed (no OS-level locking). - The fixture content specifically suggests something in the auth path can persist a non-production response body: if a refresh request ever hits a fixture/canary/staging response shaped like
{"token": "..."}, the client appears to write it to disk verbatim instead of rejecting it. Worth checking server-side too — several platforms started seeing forced logouts the same week.
Impact
Multi-session workflows (background agents, several terminals, desktop + CLI) are logged out together, interrupting all in-flight work, roughly daily. On Windows there is no keychain mitigation, and the desktop app (embedded 2.1.219) and native CLI (2.1.220) — two different versions — share the same credentials file.
Repro (as far as known)
- Windows, subscription OAuth login.
- Leave 2+
claudesessions (CLI and/or desktop app) running past the access-token lifetime. - Within ~24h, all sessions force
/login; inspect~/.claude/.credentials.jsonimmediately after — in our capture it contained the fixture value above rather than a real or empty credential.
Happy to provide timestamps, transcript excerpts, or run instrumentation (e.g. a poller hashing the credentials file like the one in #80585) on request.
This issue has 1 comment on GitHub. Read the full discussion on GitHub ↗