Skip to main content
Troubleshooting7 min readPublished September 20, 2026Updated September 22, 2026

Why am I getting a 401 error?

A 401 means no valid credential reached the server. Either nothing was sent, or what was sent was expired, malformed, or for a different project. It is an identity problem, so changing permissions will not help.

The problem

A request that should work returns 401 Unauthorized. In the interface this usually appears as a login screen you should not be seeing, an empty page, or a generic error toast.

What it means

The server received your request and could not establish who you are. This happens before any permission check — the question 'are you allowed' was never reached, because 'who are you' failed.

Common causes

  • No Authorization header was attached to the request at all.
  • The session token expired and was not refreshed.
  • The API key is wrong, revoked, or belongs to a different project or environment.
  • The key is present but sent in the wrong header — some services want `apikey`, not `Authorization: Bearer`.
  • The request runs during server rendering, where no user session exists.
  • The environment variable holding the key is unset in production, so an empty string is being sent.

How to diagnose it

  1. 1Open the Network tab, trigger the action, and select the failing request.
  2. 2Look at Request Headers. Is there an Authorization header, and does it contain a value after 'Bearer'?
  3. 3Read the response body — most services state the reason: expired, invalid, missing.
  4. 4Repeat the action signed out. If the result is identical, the credential was never being sent.
  5. 5If it is a third-party key, test the same key from a terminal to see whether the key or the app is at fault.
Testing a key outside your app
curl -i https://api.provider.com/v1/me \
  -H "Authorization: Bearer $PROVIDER_KEY"

How to fix it

CauseFix
No header sentAttach the session token in the client middleware or fetch wrapper
Expired sessionRefresh the session, or sign in again and confirm refresh works
Wrong environment keySet the correct key for this environment and redeploy
Unset variableAdd it to the hosting configuration and fail loudly when missing
Wrong header nameFollow the provider's documented header exactly
Runs during server renderingMove the call into the component or an event handler

What AI may have done

  • Written a protected call into a page loader, which runs before any session exists.
  • Invented an environment variable name that does not match the one you set.
  • Used `Authorization: Bearer` for a service that expects a plain `apikey` header.
  • Removed the middleware that attaches the token while tidying up something else.

How to verify the fix

  1. 1Repeat the original action and confirm a 2xx status in the Network tab.
  2. 2Sign out and confirm you now get a sensible signed-out experience rather than a crash.
  3. 3Sign in as a second account and confirm it works there too.
  4. 4Leave the session idle past its expiry and confirm the refresh happens silently.

How to prevent it

  • Throw a clear configuration error when a required key is missing, rather than sending an empty one.
  • Keep protected calls out of loaders on public routes.
  • Log the provider's own error text instead of replacing it with a generic message.
  • Use distinct keys per environment so a mismatch is obvious.

Frequently asked questions

Is a 401 ever the user's fault?
Yes — a long-idle tab with an expired session is normal. It should resolve itself by refreshing, not by showing an error.
Why do I get 401 only in production?
Almost always a missing or different environment variable. Compare the two environments before reading code.
Should a 401 log the user out?
Only after a refresh attempt fails. Logging out on the first 401 throws away recoverable sessions.

Practice this in MessyDev

Reading it once helps. Doing it once sticks. These are the hands-on parts of MessyDev that cover the same ground.

Keep going