Windows: stale lock directories block credential persistence after abnormal exit

Resolved 💬 3 comments Opened May 26, 2026 by dorn Closed Jun 27, 2026

Description

Claude Code on Windows creates its lockfiles as directories (mkdir-as-mutex pattern) but never removes them on abnormal exit. Once a stale lock directory exists, subsequent /login attempts silently fail to write .credentials.json even though the UI reports "Login successful."

Affected lock paths under %USERPROFILE%\.claude\:

  • .oauth_refresh.lock
  • .storage-write.lock
  • history.jsonl.lock

Steps to reproduce

  1. Run Claude Code on Windows normally.
  2. Force-kill the CC process (Task Manager, taskkill, crash, etc.).
  3. List %USERPROFILE%\.claude\ -- the .lock entries are directories (d mode), not files.
  4. Launch CC again. Session starts as "Not logged in."
  5. Run /login. OAuth flow completes, UI displays "Login successful."
  6. Status bar immediately reverts to "Not logged in. Run /login."
  7. .credentials.json is never created in .claude\.

Expected behavior

Lock directories should be cleaned up on exit (normal or abnormal), or stale locks should be detected and removed on startup (e.g., via PID check or mtime threshold).

Actual behavior

Orphaned lock directories persist indefinitely. The OAuth flow reports success because the in-memory handshake completes, but the credential-persistence step that depends on acquiring .oauth_refresh.lock silently fails. The loop is indefinite without manual intervention.

Environment

  • OS: Windows 11 Pro
  • Shell: Git Bash (MINGW64)
  • CC versions: reproduced on 2.1.91 and 2.1.150
  • Install method: npm global (%APPDATA%\npm\)
  • Account: Max subscription, healthy, well under all limits
  • Same account on a second Windows machine is unaffected (no orphaned lock dirs)

Diagnostic notes

Ruled out: account block/billing, backend incident, clock skew, Defender/EDR, DPAPI corruption, disk full, OneDrive sync, competing CC binaries, MCP configuration.

Confirmed causal by file watcher: .credentials.json is never written while the lock directories exist. Removing the lock directories restores login. The next /login recreates them as directories, but if CC exits cleanly they are removed -- until the next abnormal exit re-orphans them.

Workaround

Remove the stuck lock directories before launching CC:

find ~/.claude -maxdepth 1 -name "*.lock" -type d -exec rm -rf {} +

The -type d is critical -- only matches the stuck-directory state, not legitimate transient lock files.

View original on GitHub ↗

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