Has Claude Code suddenly thrown a message like this and demanded you log in?

Not logged in · Please run /login
Invalid API key · Fix external API key
OAuth token has expired · Please run /login
API Error: 400 ... This organization has been disabled.

These are "authentication failed (who are you?)" errors, usually surfacing as 401/403. The frustrating part is how baffling they look — "I'm paying, yet I'm rejected" or "it worked yesterday, now it suddenly wants me to log in." But most causes are textbook, and once you know the order to check, it is a quick fix.

The most important point up front. (1) The number-one auth problem is an environment variable ANTHROPIC_API_KEY silently overriding your subscription (Pro/Max) login — which becomes the real cause of unexpected pay-as-you-go charges, "organization disabled," and "Invalid API key." (2) The starting point is always /status to see "which credential is active right now." (3) When in doubt, "unset the stray key → /logout/login" for a clean re-entry.

CLAUDE CODE · AUTH PRECEDENCE

Credentials have a "precedence"

— the one higher up wins, so an env API key overrides your subscription

1 Cloud (Bedrock/Vertex/Foundry)
2 ANTHROPIC_AUTH_TOKEN (gateways)
3 ANTHROPIC_API_KEY ← env var this wins = pay-as-you-go
4 apiKeyHelper / 5. CLAUDE_CODE_OAUTH_TOKEN
6 Subscription OAuth (/login) what you actually want

If ANTHROPIC_API_KEY lingers in your environment, it takes precedence over the subscription.
First check with /status → if unneeded, unset ANTHROPIC_API_KEY.

1. What this error is telling you

Authentication means "proving who you are." Claude Code proves "you" with either your subscription OAuth login, an API key, or cloud credentials. When that proof fails, you are rejected as 401 (authentication_error) or 403 (forbidden). The representative messages and meanings:

MessageMeaning
Not logged in · Please run /loginNo valid credential → /login
Invalid API key · Fix external API key (older builds: "· Please run /login")A key from an env var or apiKeyHelper was rejected by the API
This organization has been disabledA stale API key from a disabled org is overriding you
OAuth token revoked / has expired · Please run /loginSigned out elsewhere / admin revoked / auto-refresh failed
API Error: 403 ... forbidden ... Request not allowedInactive subscription, missing Console role, or proxy interference

The key habit: before blaming yourself, run /status to see "which credential is active right now." Most auth errors stem from an unintended credential being selected — and the prime suspect is the "API key override" in the next section.

2. The big trap — an API key overrides your subscription

The official docs state that Claude Code picks ONE credential by "precedence" (see the hero). The catch is that the environment variable ANTHROPIC_API_KEY sits ABOVE your subscription (Pro/Max) login. In other words —

The official explanation (paraphrased)

"Even with an active subscription, if ANTHROPIC_API_KEY is set in your environment, it takes precedence once approved. If that key belongs to a disabled or expired org, authentication fails. Run unset ANTHROPIC_API_KEY to fall back to your subscription, and check /status to confirm which is active."

This override produces three "baffling" symptoms. (1) Unexpected pay-as-you-go charges — what should be a flat subscription gets billed per token via the API key (large surprise bills have been reported). (2) This organization has been disabled — the leftover key belonged to a disabled old org. (3) Invalid API key — the key is expired or wrong. None of these is "a problem with your login" — they are "a problem of a stray key squatting in your environment."

Where the key comes from: an export ANTHROPIC_API_KEY=... in ~/.zshrc / ~/.bashrc / ~/.profile; a .env read by direnv, dotenv, or your IDE terminal; a leftover from a previous job/project; a CI environment. On Windows, the PowerShell profile ($PROFILE) or User environment variables. Detect with /status and env | grep ANTHROPIC; fix with:

# Temporarily unset and launch
unset ANTHROPIC_API_KEY
claude

# Permanent fix: remove the export line from your shell config / .env, then confirm with /status

Note: in interactive mode you are asked once whether to use the key, and your choice is remembered (change it later via the "Use custom API key" toggle in /config). Unless you deliberately want to use the API key, confirm with /status that the subscription is active.

3. Other causes

Auth issues other than the override also tend to have fixed causes.

OTHER CAUSES

Auth stumbles beyond the override

Token revoked / expired
Signed out elsewhere / admin revoked / refresh failed. Re-enter with /logout/login.
System clock skew
Token validation depends on accurate time. If you are asked to log in every launch, fix the clock.
macOS Keychain
A locked Keychain / password mismatch prevents saving credentials. Check with claude doctor.
Missing Console role (403)
For API-key use, confirm a "Claude Code" / "Developer" role in the Console and an active subscription.
OAuth in WSL/SSH/containers
The browser redirect cannot return locally. Paste the shown code, press c to copy the URL, or set BROWSER.
Org policy
"Disabled subscription access / API key auth" are server-side settings you cannot override locally. Admin must act.

"Asked to log in every time" → suspect clock skew or Keychain first.
"Rejected with 403" → suspect inactive subscription, Console role, or proxy.

Knowing where credentials live also speeds recovery. macOS: Keychain; Linux: ~/.claude/.credentials.json (mode 0600); Windows: %USERPROFILE%\.claude\.credentials.json. Normally /login and /logout manage these, but if the store is corrupted you can delete this file for a clean re-auth (advanced).

4. The diagnostic workflow

When stuck on auth, go top-down. Most cases resolve by step 3.

DIAGNOSE

Isolate it top-down

1
/status to see which credential is active (subscription, API key, or cloud).
2
env | grep ANTHROPIC (Windows: $PROFILE / User env vars) to find a stray key.
3
unset ANTHROPIC_API_KEY → relaunch. Make it permanent by removing the export line from your shell config / .env.
4
Still failing? /logout → close Claude Code → /login for a clean re-auth.
5
Fix the clock / check the Keychain with claude doctor (macOS) / confirm your Console role (orgs).

The rule: "first /status, then hunt for the stray key."
Most cases are fixed by simply removing the key that was overriding you.

5. Telling it apart from similar errors

"Rejected / stopped" can have non-auth causes too. Splitting by the HTTP code is the reliable way.

SymptomWhat it really isMain fix
401 / 403 · Invalid API key · Not logged inThis article = auth (credential problem)/status → remove stray key → /login
usage limit reachedPlan quota exhausted (auth is fine)Wait for reset; fixes
429 Request rejectedRate limit (a low-tier key override can cause a 429)Slow down; also check /status for a stray key
529 / 500Server-side overload / internal errorWait & retry; fixes
Credit balance is too lowConsole prepaid balance exhausted (bill or switch to subscription)Add credits, or /login to a subscription

A mnemonic: 401/403 is the "who are you?" problem = auth. usage limit and Credit balance are "amount / balance" problems. 429 is rate, 529/500 is server-side. Notably, a stray API key causes not just "auth failure" but also "unexpected charges" and "a 429 on a low tier" — which is why the answer to confusion is always /status first. For other common errors, see the error roundup.

6. Prevention checklist

A checklist to stop getting stuck on auth repeatedly.

(1) If you use the subscription, do not leave ANTHROPIC_API_KEY in your shell config / .env (watch for leftovers from old jobs/projects). (2) Make a habit of /status to confirm the active credential before important work. (3) For CI, use claude setup-token's CLAUDE_CODE_OAUTH_TOKEN (or an explicit API key) instead of interactive login. (4) If you are asked to log in every time, check the system clock and the macOS Keychain. (5) For org accounts, confirm the Console role and plan status. (6) In WSL/SSH, know the paste-the-code method.

Summary

Claude Code's auth/login errors (Not logged in / Invalid API key / organization disabled / OAuth token expired, etc.) are mostly 401/403 = credential problems. The most frequent true cause is "the environment variable ANTHROPIC_API_KEY silently overriding your subscription login" — which produces unexpected pay-as-you-go charges, organization disabled, and Invalid API key. So the starting point is always /status to see "which credential is active."

Diagnose by (1) /status -> (2) env | grep ANTHROPIC to hunt a stray key -> (3) unset + remove from shell config -> (4) /logout -> /login -> (5) clock / Keychain / Console role. Most cases are fixed by simply removing the key that was overriding you. Split by 401/403 = auth, usage limit / Credit = amount-balance, 429 = rate, 529/500 = server to avoid the wrong fix. Related: usage limit, 529/500 errors, Claude Code error roundup.

FAQ

Q. I'm paying, yet I get "Invalid API key" or "organization has been disabled." Why?
A. Almost certainly, an environment variable ANTHROPIC_API_KEY is overriding your subscription login. If that key belongs to an expired or disabled org, you get rejected even with an active subscription. Find it with env | grep ANTHROPIC, run unset ANTHROPIC_API_KEY, then /login and confirm with /status. Also remove the export line from your shell config (.zshrc, etc.) or .env.

Q. I'm on a flat subscription but got billed per token.
A. This too is typically the ANTHROPIC_API_KEY override. When the API key takes precedence, usage flows to per-token API billing instead of your flat subscription. Confirm with /status that "the subscription is active"; if the API key is selected, remove it with unset + config cleanup. Keep it only if you intend to use the API key.

Q. I'm asked to log in every time I start.
A. The common causes are (1) system clock skew (token validation depends on accurate time) and (2) a locked macOS Keychain / password mismatch that prevents saving credentials. Set the clock to auto-sync, and on macOS check the Keychain with claude doctor. If it persists, re-enter cleanly with /logout/login.

Q. What does /status tell me?
A. It shows which authentication method/credential is currently active (subscription OAuth, ANTHROPIC_API_KEY, or cloud credentials). Since most auth trouble is "an unintended credential being selected," /status first is the rule. The exact display varies by version, so confirm current behavior in the official docs.

Q. Login fails over WSL or SSH because the browser does not open.
A. On remote setups, the browser redirect cannot return to the local callback. Work around it by pasting the login code Claude Code shows, pressing c to copy the URL and opening it in your local browser, or setting the BROWSER environment variable on WSL2. Knowing the paste-the-code method makes this reliable.