Claude Code API Error 401 OAuth token has expired: 5 Proven Fixes (Tested)
Claude Code API Error 401 OAuth token has expired means the login token expired and the automatic refresh failed. We reproduced it on Claude Code 2.1.312 with a mock API and list the fixes for /login users, CLAUDE_CODE_OAUTH_TOKEN, scripts and the SDK.

Short answer: Claude Code API Error 401 OAuth token has expired means the API rejected the login token Claude Code sent, because it expired and the automatic refresh didn’t work. The full line usually reads Please run /login · API Error: 401 OAuth token has expired. Please obtain a new token or refresh your existing token. Run /login and sign in again; that fixes most cases. If you set CLAUDE_CODE_OAUTH_TOKEN yourself (CI, scripts, Docker), /login alone won’t change what new sessions use: generate a new token with claude setup-token and replace the old value. We reproduced the error on Claude Code 2.1.312 with a mock API and an expired token; the output is below. Wording and fixes follow the official Claude Code error reference, checked on October 29, 2026.
What Claude Code API Error 401 OAuth token has expired means

The docs group two messages together. OAuth token revoked · Please run /login means you signed out everywhere or an admin removed your access. Please run /login · API Error: 401 OAuth token has expired ... means the token expired and the automatic refresh failed mid-session. Both are rejections the API returned for a request Claude Code actually sent.
In -p mode and the Agent SDK the same error reads:
Failed to authenticate. API Error: 401 OAuth token has expired ...
and the structured error code is authentication_failed. Three nearby messages look similar but mean something else:
Login expired · Please run /login: Claude Code already failed to renew your saved login and cleared it, so it stops the request locally before sending it.API Error: 401 Invalid authentication credentials: the token isn’t expired; the account, organization or API key behind it is no longer accepted.Not logged in · Please run /login: no credential was found at all.
Our test: an expired token on every request

We can’t make a real subscription token expire on demand, so we pointed Claude Code 2.1.312 at a local mock server with ANTHROPIC_BASE_URL. The mock answers every request with a 401 and the body {"type":"authentication_error","message":"OAuth token has expired. Please obtain a new token or refresh your existing token."}, the same text users quote in GitHub reports. We set CLAUDE_CODE_OAUTH_TOKEN to a dummy sk-ant-oat01-... value.
claude -p hiprintedFailed to authenticate. API Error: 401 OAuth token has expired. Please obtain a new token or refresh your existing token.With--output-format json, the result had"is_error": trueand"api_error_status": 401.- The mock logged 4 requests, all carrying
Authorization: Bearer sk-ant-oat01-.... Claude Code kept sending the variable’s value, as the docs describe. claude auth statusstill said"loggedIn": true, "authMethod": "oauth_token". That command only reports which credential is configured; it doesn’t check whether the token still works.- After
unset CLAUDE_CODE_OAUTH_TOKENwith no saved login, the result wasNot logged in · Please run /login. With an API key pointed at a mock that answers normally, the same prompt returned a reply.
For comparison, a malformed token sent to the real API returned API Error: 401 OAuth access token is invalid., which is a different message from expired.
How to fix Claude Code API Error 401 OAuth token has expired

- Check which credential is active. Run
/status. A token you set yourself shows as anAuth tokenrow readingCLAUDE_CODE_OAUTH_TOKEN. - Saved login: run
/loginin the session and sign in again. -por Agent SDK with a saved login: runclaudein the same environment, complete/login, then rerun your command.CLAUDE_CODE_OAUTH_TOKEN: runclaude setup-tokenon a machine with a browser, copy the token it prints, and replace the old value:
export CLAUDE_CODE_OAUTH_TOKEN=your-new-token
The docs say setup-token creates a one-year token and doesn’t save it anywhere. If the old value lives in your shell profile or the env block of a settings.json file, change it there too, or new sessions will keep reading it. Before v2.1.225, Claude Code could swap the variable’s value for a short-lived stored token mid-session, which then expired again; update if you’re older than that.
- Automation without a browser: use
ANTHROPIC_API_KEYinstead, or asetup-tokentoken. - Asked to log in on every launch: check that the system clock is right, since token validation depends on it. On macOS, run
claude doctorand follow the Keychain steps in the login troubleshooting guide.
Pick the fix by how you sign in

Since v2.1.210, /status also shows a Login row reading Expired — log in again when a saved login can’t be refreshed. The authentication docs add that Claude Code warns Your login expires in 3 days · run /login to renew at startup, so renewing then avoids a failure halfway through a long unattended task. If you still need to set up the CLI, start with our Claude Code install guide.
When /login doesn’t help: GitHub reports
These reports were filed on older versions and are now closed, but they describe what people ran into:
- Issue #15007: after a 401 in an active session,
/logincompleted in the browser but the session kept failing. One commenter on Windows said quitting and restarting Claude got them out. - Issue #44729:
/loginopened the browser but failed withOAuth error: timeout of 15000ms exceeded. - Issue #33291: in the VS Code extension, during a Claude incident on the status page, the reporter fixed it by running
claude auth loginin a terminal.
So if /login succeeds and the next prompt still fails, exit Claude Code, start it again (use claude --continue to get the conversation back) and retry. For browser sign-in problems in WSL2, SSH or containers, see the official steps. More errors are collected in our Claude Code errors hub.
FAQ
Does Claude Code API Error 401 OAuth token has expired mean my subscription ended?
No. It is about the login token. Removed access shows up differently: OAuth token revoked when an admin removes it, or Invalid authentication credentials when an account or organization is disabled.
Why does claude auth status say I’m logged in?
It reports which credential is configured, not whether the API still accepts it. Our test showed loggedIn: true with an expired token.
How long does a setup-token token last?
The docs say one year.
Will an API key fix it?
Yes, if you are fine paying API rates. An ANTHROPIC_API_KEY takes precedence over a subscription login (in interactive mode Claude Code asks once whether to use it); see our Claude usage limits guide for how subscription limits compare.