[BUG] macOS: locked login keychain silently breaks auth — /login falsely reports "Login successful", and entering the password at the keychain prompts still leaves the session logged out

Status Open
Reported on v2.1.215
Maintainer reply None cached
Activity 0 comments · opened Jul 20, 2026

Summary

When the macOS login keychain is locked (or otherwise inaccessible, e.g. errSecAuthFailed), Claude Code:

  1. treats the user as logged out with a generic Not logged in · Please run /login — no hint that the keychain is the cause;
  2. lets /login run the full browser OAuth flow and print "Login successful", even though the token is never persisted (the write silently fails), producing an endless login loop;
  3. in the deterministic repro below (security lock-keychain), triggers two consecutive security wants to use the "login" keychain password prompts on startup — but even when the correct password is entered and OK'd at those prompts, the session still starts logged out. Only a manual security unlock-keychain before launching claude restores auth.

Notably, in the original organically-hit incident (details below) no keychain prompts appeared at all — the failure was completely silent, which is what made it undiagnosable from inside Claude Code. The prompts only show up in the manual lock-keychain repro.

Once the keychain is unlocked externally, the previously-stored token works immediately — no re-login is needed — proving the credential was intact the whole time and every part of the loop above was avoidable.

Environment

  • Claude Code 2.1.215, native install (~/.local/bin/claude → ~/.local/share/claude/versions/2.1.215)
  • macOS 26.5.1 (25F80), Apple Silicon (arm64, Mac16,5)
  • Shell: fish; launched from a terminal
  • Auth: Claude Max account (OAuth); credentials stored in macOS Keychain (no ~/.claude/.credentials.json fallback file present)
  • Reproduced in both the default config dir and a second CLAUDE_CONFIG_DIR workspace (they share the keychain entry, as expected)

Deterministic reproduction

Starting state: logged in and working, OAuth token in the login keychain.

  1. security lock-keychain ~/Library/Keychains/login.keychain-db
  2. Run claude and submit any prompt.
  3. Observed: two sequential security wants to use the "login" keychain password dialogs appear during startup.
  4. Enter the correct keychain password and click OK on the dialog(s).
  5. Observed: the session still shows Not logged in · Please run /login. /status shows no active auth.
  6. Run /login, complete the browser OAuth flow.
  7. Observed: Login successful is printed — but the very next prompt again fails with Not logged in · Please run /login. This loops indefinitely; .claude.json gets the oauthAccount metadata written (so the banner shows the account/org), but the token itself is never saved.
  8. Quit, run security unlock-keychain ~/Library/Keychains/login.keychain-db, relaunch claude.
  9. Observed: logged in immediately, no /login required — the original stored token still works.

How this bites in the real world (original incident — fully silent variant)

This was first hit organically, not via a deliberate lock: the login keychain got into a state where security show-keychain-info returned errSecAuthFailed ("The user name or passphrase you entered is not correct"). In that state, no keychain password prompts were ever shown — the only symptom was Claude Code repeatedly claiming a successful login and then immediately asking to log in again, in every workspace, with nothing pointing at the keychain. (Had a keychain prompt appeared, the cause would have been obvious.) The background daemon's proactive OAuth refreshes had been succeeding right up until the keychain became inaccessible, then everything broke silently. Diagnosis required manually poking at security, which most users won't think to do.

What put the keychain into that state is unknown — possibly a macOS issue, possibly a side effect of unrelated development activity on the machine (Xcode / StoreKit testing was in use around that time). Regardless of the trigger, the repro above shows the failure handling is deterministic: any locked-keychain state produces the same silent login loop, with or without the OS prompts.

Expected behavior

  • /login should verify the credential actually round-trips (write → read back) before printing "Login successful". A failed keychain write should be a loud, explicit error.
  • When a credential read fails with a keychain-level error (errSecAuthFailed, keychain locked, user cancelled), the message should say so and suggest the fix (e.g. "your login keychain is locked — run security unlock-keychain ~/Library/Keychains/login.keychain-db or open Keychain Access"), instead of the generic Not logged in · Please run /login — which is actively misleading here, since /login cannot fix it.
  • If the OS unlock prompt is shown and the user successfully authorizes it, that access should be used — currently the prompt is presented (twice) and the granted access is apparently discarded, which is the most confusing part: the user does everything right and still ends up logged out. It looks like the auth state may be decided before/regardless of the prompt outcome, or a failed first read is cached and never retried.
  • Consider falling back to the file-based credential store (as on Linux) with a warning when the keychain is unavailable, rather than entering an unrecoverable loop.

Related issues (similar symptoms, different triggers/root causes)

  • #73861, #70077 — /login reports "Login successful" but credentials never written to the Keychain (no keychain-lock repro identified there)
  • #76014 — OAuth login succeeds but token never persisted; doctor blames keychain writability
  • #68195, #77697 — repeated keychain permission dialogs

This report adds (a) a deterministic one-command repro (security lock-keychain), (b) evidence that the stored token survives and works after unlock with no re-login, and (c) the detail that answering the keychain password prompts correctly still does not recover the session.

View original on GitHub ↗