How to fix: 401 authentication error / invalid API key
Last verified: June 2026· All LLM providers
Where this shows up
All LLM providers
How it shows up
The same root cause surfaces in a few different ways. If any of these match, you're in the right place.
- Every request fails immediately with
401, regardless of model or payload — the request never reaches the model, so latency is near-zero. - The same key works from your laptop but fails in CI, staging, or a container.
- It worked yesterday and broke with no code change — usually a rotated, expired, or revoked key.
- Only some routes fail, while others succeed — you have more than one key in play and one of them is wrong.
- The error body says
invalid_api_key,authentication_error,Incorrect API key provided, orUnauthorized.
Diagnose it first
Confirm which cause you actually have before changing anything — most wasted time here comes from fixing the wrong one.
| Check | What the result tells you |
|---|---|
| Print the key length and last four characters at startup (never the whole key). | Empty or much shorter than expected means the variable never loaded — a .env file not read, or a missing secret in the deploy environment. |
Call the provider directly with curl using the same key. | If curl works and your app does not, the problem is in the SDK config or header, not the key itself. |
| Check for leading/trailing whitespace or quotes in the environment value. | A trailing newline from a copied secret or quotes preserved by a shell will produce a 401 for a key that is otherwise valid. |
| Confirm which header the SDK is actually sending. | Sending a key in Authorization: Bearer to a provider that expects x-api-key (or the reverse) always returns 401. |
| Check whether the key is scoped to the project, org, or model you are calling. | A valid key with no access to that workspace or model returns 401 or 403 depending on provider — the key is real but not entitled. |
The fix
- 1Confirm the key is set in the environment and loaded — not hardcoded, not an empty string.
- 2Check you’re not setting two conflicting credentials at once (e.g. both an API key and an auth token) — some SDKs send both and the API rejects it.
- 3For OAuth/bearer tokens, send them in the
Authorization: Bearerheader, not the API-key header. - 4Verify the key hasn’t been revoked and has access to the model/workspace you’re calling.
- 5Rotate the key if it may have leaked, and move it into a secrets manager.
Provider-specific behaviour
The error means roughly the same thing everywhere, but each provider signals it differently.
- OpenAI
- Expects
Authorization: Bearer. Project-scoped keys (sk-proj-…) are bound to one project — if you also sendOpenAI-OrganizationorOpenAI-Projectheaders, they must match the key's project or the call is rejected. The JSON body carries a machine-readableerror.codesuch asinvalid_api_key. - Anthropic
- Expects
x-api-key:, **not**Authorization: Bearer. This is the single most common cause of a 401 when porting code from an OpenAI-shaped client. Theanthropic-versionheader is also required; omitting it produces a different 400-class error, so a 401 here is genuinely the key or its header. - Google (Gemini)
- Accepts the key as an
x-goog-api-keyheader or a?key=query parameter. Keys can be restricted by referrer or IP in the Google Cloud console — a key that works locally and fails from a server is usually hitting an API-key restriction, not an invalid key. - Azure OpenAI
- Uses the
api-keyheader for key auth, or an AAD bearer token for identity-based auth — the two are not interchangeable. A 401 here often means the resource endpoint, deployment name, orapi-versiondoes not match the key's resource. - AWS Bedrock
- Does not use API keys at all — it authenticates with SigV4 from the standard credential chain. A 401/403 means expired STS credentials, a missing region, or an IAM policy without
bedrock:InvokeModel, not a bad key string.
What doesn't work
Common fixes for this error that look right and aren't.
Regenerating the API key as the first step.
If the cause is a missing environment variable or the wrong header, a new key fails identically — and you have now invalidated the old key for every other service still using it correctly.
Hardcoding the key "just to test".
It usually proves the key is fine while masking the real config bug, and the temporary key reliably survives into a commit. If you must isolate it, use
curloutside the codebase instead.Adding a retry loop around the 401.
401 is a deterministic authentication failure, not a transient one. Retrying cannot succeed, and it turns one clear error into a burst of identical failures that is harder to read in logs.
Prevent it
Load keys from a secrets manager, never commit them, and scope keys narrowly per service.
Common variations and related errors
You'll usually hit this same root cause under a few different names. Same fix.
- "401 unauthorized"
- "invalid API key"
- "Incorrect API key provided"
- "Authentication credentials not found"
- "expired token"
- "invalid_api_key"
Frequently asked questions
What causes “401 authentication error / invalid API key”?
The API key is missing, malformed, revoked, or sent the wrong way (e.g. an OAuth token in the API-key header).
How do I prevent “401 authentication error / invalid API key” from recurring?
Load keys from a secrets manager, never commit them, and scope keys narrowly per service.
Why does my API key work locally but return 401 in production?
Almost always an environment difference rather than the key. The usual causes: the secret was never added to the production environment, the deploy platform injects it under a different variable name, the value picked up a trailing newline when it was pasted, or the key is IP/referrer-restricted and your server's address is not on the allow-list. Log the key length and last four characters at startup in both environments and compare.
What is the difference between a 401 and a 403 from an LLM provider?
401 means the request was not authenticated — the credential is missing, malformed, expired, or sent in the wrong header. 403 means you were authenticated successfully but are not authorised for that specific action, such as a valid key calling a model your organisation has not been granted access to. If you see 403, stop checking the key and start checking entitlements and IAM policy.
Can a rate limit cause a 401?
No. Rate limiting returns 429 and quota exhaustion typically returns 429 or a billing-specific error. If you are getting 401 the request is being rejected before any usage accounting happens, so the cause is authentication, not volume.