Skip to content

API Error: 401 {"type":"error","error":{"type":"authentication_error","message":"OAuth authentication is currently not supported."}}

Read the message, not the status code. This is a well-formed error body from a server that received your request, parsed your credential, recognised what kind of credential it was, and declined that kind. It is not a broken login, not a revoked token, not a network fault, and not a quota problem — all of which would produce different wording or no body at all.

The practical consequence is blunt: your sign-in is working, and running /login again will hand the same endpoint the same kind of credential and get the same 401 back.

The status code and the message disagree about what is wrong

Per the API error reference, 401 with error.type: authentication_error generally means an API key is malformed, revoked, or expired. That is the reading almost everyone applies here, and it sends them to the console to regenerate something.

This particular message says something else. “OAuth authentication is currently not supported” is a statement about the authentication scheme, not about the validity of your credential. The server is saying: whatever you sent was intelligible, and this endpoint does not accept that form of it. A malformed token does not produce a message naming OAuth; a server that could not understand your credential would not be able to tell you which scheme it was.

So the failure is a mismatch between two things that are each individually fine: a subscription sign-in that works, and an endpoint that wants an API key.

Where the mismatch comes from

Claude Code can be pointed at more than one place. ANTHROPIC_BASE_URL sends its traffic to a gateway instead of directly to Anthropic — the docs note that error text changes to name the gateway host when this is set, which is a useful tell that you are not talking to who you think you are. Cloud deployments are the other family: Amazon Bedrock, Google Cloud and Microsoft Foundry are documented as API-key/cloud-credential paths, distinct from a claude.ai subscription sign-in.

Any of those targets can be perfectly healthy and still have no idea what to do with a subscription token. The same applies to a third-party relay, a self-hosted proxy, a team’s internal gateway, or a script that reuses Claude Code’s credential against a raw API endpoint it was never issued for.

A note on the word “currently”: it is in the vendor’s message for a reason, and it means this page should not be read as a permanent law. Treat the message as describing the endpoint you are talking to today. Claude Code’s behaviour and error strings are version-gated in the official docs often enough that a scheme’s support status is a moving target — check what your target endpoint documents rather than assuming the shape of this error is eternal.

The fix runs in the opposite direction from the usual one

This is the part worth carrying away. The most common auth misconfiguration in Claude Code is a stray ANTHROPIC_API_KEY in the environment shadowing a subscription — the docs call that out explicitly as the reason subscribers see Console-billing symptoms, and the standard remedy is to unset it.

Here the remedy is the reverse: you need an API key, and the OAuth credential is what is in the way. Unsetting the key would make this error worse, not better, because it removes the only credential the endpoint would have accepted. Advice copied from the invalid-key page will actively hurt you here, and that page’s advice is correct for its own error. The variable is the same; the direction is not.

/status is what settles which situation you are in. It shows the active settings sources and which credential is active, so it tells you both what you are sending and — via the settings source — where that came from.

Telling the causes apart

/status shows a subscription sign-in, and ANTHROPIC_BASE_URL is set. You are sending a subscription token to a gateway. Confirm by checking what that host expects; a relay that terminates and re-signs requests almost always wants an API key of its own.

You are on Bedrock, Google Cloud, or Microsoft Foundry. These paths take their own credentials. A /login sign-in is not one of them, and no amount of re-authenticating with claude.ai will produce one.

It works in your interactive session and fails in a script, a hook, or an SDK app. The two contexts resolved different credentials. Compare what /status reports interactively against what the script’s environment actually contains — the script may be inheriting an OAuth credential from your profile while targeting an endpoint configured for keys.

It started the day someone added a corporate gateway or an enterprise policy. Managed settings are applied from a system directory, so the change may not be visible anywhere in your own files. Check with your administrator which credential the gateway expects before you touch anything locally.

Nothing changed on your side and every endpoint fails. Then the endpoint’s own policy changed, and this is not yours to fix — verify against the vendor’s documentation for the endpoint before spending an afternoon on your config.

Is retrying useful?

No. This is a policy decision, and policy decisions are identical on every attempt.

There is no capacity involved, no retry-after header to honor, and no backoff that converts an unsupported scheme into a supported one. The response arrived promptly and completely — the presence of a parsed JSON body is itself proof that the round trip worked. A retry re-runs a completed negotiation with unchanged inputs.

If a wrapper is retrying this for you, turn it off for this error class. All it buys is a longer wait before you read the message, and the message is the entire diagnosis.

Fix by scenario

  • Gateway or relay in the path — obtain and configure the credential that gateway issues, or remove ANTHROPIC_BASE_URL and go direct if your subscription is meant to be the credential.
  • Cloud provider deployment — configure that provider’s credentials. The subscription sign-in is not portable into Bedrock, Google Cloud or Microsoft Foundry.
  • Script or CI inheriting the wrong credential — set the credential explicitly for that context instead of relying on what your shell happens to export. Never write the key into the repository or echo it into a build log; CI logs outlive the key.
  • Endpoint genuinely does not support the scheme — switch the credential type rather than the credential. Regenerating anything is wasted motion.

Whatever you do here, do not paste a key into a chat window, a web form, or a third-party site to “test” whether it is accepted. The only safe test is a real request from your own machine.

How to confirm it’s fixed

/status naming the credential type the endpoint expects is step one, and a successful request against that same endpoint is step two. Do not accept a success obtained by quietly falling back to a different target — if you removed ANTHROPIC_BASE_URL to make the error go away, confirm that is the configuration you intended to run, not a workaround you will rediscover in a month.

Then repeat from a newly launched process. A session started before your change still holds the old environment and will keep producing the old result, which reads as “the fix did not work” when it simply has not been loaded.

If your login itself is failing rather than your requests, you are on the exchange side of this cluster, not the credential side: a login that returns a 500 got a real answer from the auth server, while a login that times out at a fixed deadline never got one in time. A bare AxiosError: Request failed with status code 401 with no JSON body is a different beast again — no body means no error type to read, and the diagnosis shifts to which client sent it. The AI coding error triage tool separates these by whether a request was refused, unanswered, or never made.