New troubleshooting article for the recurring 'security wants to access Claude Code-credentials' prompt that persists even after Always Allow (ACL invalidation on binary-signature change / token refresh / post-boot churn). Covers triage, the reset-and-relogin fix, and the file-based credentials workaround with its plaintext tradeoff. Registered in SUMMARY + troubleshooting index; cross-linked with the corrupt-credential login-failure article (distinct symptom).
66 lines
3.2 KiB
Markdown
66 lines
3.2 KiB
Markdown
---
|
||
title: "Claude Code Won't Log In (Warp & iTerm2) — Corrupt Keychain Credential"
|
||
domain: troubleshooting
|
||
category: claude-code
|
||
tags: [claude-code, authentication, oauth, keychain, macos, warp, iterm2]
|
||
status: published
|
||
created: 2026-06-09
|
||
updated: 2026-06-09
|
||
---
|
||
|
||
# Claude Code Won't Log In (Warp & iTerm2) — Corrupt Keychain Credential
|
||
|
||
## Symptom
|
||
Claude Code (v2.1.169) would not log in from Warp. The login flow never completed.
|
||
The same failure occurred in iTerm2, which ruled out a terminal-specific cause.
|
||
|
||
## Investigation path
|
||
1. **Version** — `claude --version` = 2.1.169. Already well past the v2.1.105–2.1.107
|
||
bracketed-paste regression (fixed in 2.1.108), so the known paste bug was not it.
|
||
2. **Environment / overrides** — none of `ANTHROPIC_API_KEY`, `CLAUDE_CODE_OAUTH_TOKEN`,
|
||
`ANTHROPIC_AUTH_TOKEN`, `ANTHROPIC_BASE_URL`, or `CLAUDE_CODE_PATH` were set, so no stale
|
||
key or shim was hijacking auth. System clock was correct (rules out token-time skew).
|
||
3. **Account record** — `~/.claude.json` had `oauthAccount` and `userID` populated
|
||
(`maj.linux@gmail.com`), i.e. Claude Code believed it already had an account.
|
||
4. **Keychain** — a `Claude Code-credentials` generic-password item existed, but
|
||
`security find-generic-password -s "Claude Code-credentials" -w` returned an
|
||
**empty / non-JSON payload** (failed to parse). The credential entry was present but
|
||
its secret was empty/corrupt.
|
||
|
||
## Root cause
|
||
A **corrupt (empty) Keychain credential** named `Claude Code-credentials`. Claude Code saw
|
||
an existing credential, tried to read/refresh it, failed to parse it, and wedged *before* it
|
||
could start a clean login. Because the account also existed in `~/.claude.json`, the CLI kept
|
||
trying to use the broken credential instead of prompting fresh auth. This is system-level
|
||
(Keychain), which is why it reproduced across both Warp and iTerm2.
|
||
|
||
## The fix
|
||
```bash
|
||
# 1. Remove the broken credential
|
||
security delete-generic-password -s "Claude Code-credentials"
|
||
|
||
# 2. Re-authenticate
|
||
claude # then /login, or:
|
||
claude /login
|
||
```
|
||
If `/login` still hangs after that, also clear the stale account record and retry:
|
||
```bash
|
||
cp ~/.claude.json ~/.claude.json.bak
|
||
python3 -c "import json,pathlib; f=pathlib.Path.home()/'.claude.json'; d=json.load(open(f)); d.pop('oauthAccount',None); json.dump(d,open(f,'w'),indent=2)"
|
||
claude /login
|
||
```
|
||
Resolved on step 1+2 — login succeeded after deleting the corrupt Keychain item.
|
||
|
||
## Notes
|
||
- On macOS, Claude Code credentials live in the **login Keychain** (`Claude Code-credentials`),
|
||
not in `~/.claude/.credentials.json` (that path is Linux/other).
|
||
- Quick triage command to spot the same failure again:
|
||
```bash
|
||
security find-generic-password -s "Claude Code-credentials" -w | python3 -m json.tool
|
||
```
|
||
If that errors with "Expecting value", the stored secret is empty/corrupt — delete and re-login.
|
||
|
||
## Related
|
||
- [Claude Code Keychain Prompt Keeps Reappearing on macOS (ACL Invalidation)](claude-code-keychain-prompt-recurring-macos.md) — different symptom: login works but the permission prompt won't stop
|
||
- Config: `~/.claude.json` (oauthAccount, userID), login Keychain item `Claude Code-credentials`
|
||
- Other Claude Code note: `claude-mem-setting-sources-empty-arg.md`
|