401 Unauthorized

The server couldn’t confirm who was calling: the request had no credentials, or its API key, session, or token was wrong or expired.

Browser console
GET https://api.example.com/items 401 (Unauthorized)

Also appears as

  • Failed to load resource: the server responded with a status of 401 (Unauthorized)
  • AxiosError: Request failed with status code 401

Prompt to fix it

Requests to our API fail with "401 Unauthorized". Find the failing request and check which credentials it sends: an Authorization header, an API key header, or cookies. Trace where that token or key comes from and fix the cause: attach a fresh token to every request, wait for sign-in before calling, refresh expired sessions, and make sure production uses the right key from environment variables. If the API is on another domain and uses cookies, set credentials: "include" and the matching CORS headers. Don’t remove the server’s auth check, and don’t put a secret key in frontend code.

Paste into Layerwise or any AI coding tool.

What it means

A 401 means the server needs to know who is calling and couldn’t confirm it. The request arrived with no credentials, or with an API key, session cookie, or token the server rejected. Despite the name, it’s about identity: the server is asking you to sign in.

Look at the request headers in the Network tab. Most APIs expect Authorization: Bearer <token>, and Supabase also expects an apikey header. Cookies only go to another domain when the request sets credentials: 'include'. A missing header means the code never attached it; a present one means the value is wrong for this server or has expired.

Timing causes many of these. A request that fires before sign-in finishes, or just after a token expires, carries no valid token even though the user looks signed in. On a published site, also confirm production uses production keys, because a test key or one from another project fails every time.

Common causes

  • The request has no Authorization header, because the code never attaches the token or runs before sign-in finishes.
  • The token or session expired, and the app doesn’t refresh it.
  • An environment variable holds the wrong key: a test key, a key from another project, or a value with extra spaces or quotes.
  • Sign-in uses cookies, and a request to another domain leaves them out because it lacks credentials: 'include'.

How to fix it

  1. In the Network tab, open the failing request and check whether Authorization, apikey, or Cookie headers were sent.
  2. Read the response body. Most APIs say whether the key is missing, invalid, or expired.
  3. Attach the current token to every request, reading it from your auth library right before the call.
  4. Compare the key in your host’s environment variables with the provider’s dashboard, then redeploy, since many hosts apply new values only on the next deploy.
  5. If the server reads a cookie from another domain, send requests with credentials: 'include' and allow credentials in its CORS setup.

Example fix

import { supabase } from './supabase';

export async function apiFetch(path: string, init: RequestInit = {}) {
  // getSession refreshes an expired access token before returning it.
  const { data } = await supabase.auth.getSession();
  const token = data.session?.access_token;
  if (!token) throw new Error('Not signed in');

  const headers = new Headers(init.headers);
  headers.set('Authorization', `Bearer ${token}`);
  return fetch(`${import.meta.env.VITE_API_URL}${path}`, { ...init, headers });
}
All errors
JWT expired

JWT expired

A request carried a sign-in token past its expiry time, usually because code saved the token once instead of using the refreshed one.

AuthSessionMissingError: Auth session missing!

AuthSessionMissingError: Auth session missing

A Supabase auth call needed a signed-in user, but the client making it had no session, often because it runs on the server without cookies.

GET https://api.example.com/items 403 (Forbidden)

403 Forbidden

The server knows who is calling and still refuses, because that user, key, or visitor lacks permission for this request.

Access to fetch at 'https://api.example.com/items' from origin 'http://localhost:5173' has been blocked by CORS policy: No 'Access-Control-Allow-Origin' header is present on the requested resource. If an opaque response serves your needs, set the request's mode to 'no-cors' to fetch the resource with CORS disabled.

Blocked by CORS policy

The browser hid a response from another site because that server never said your site is allowed to read it.

Build with an agent that checks its work

The Layerwise agent clicks through the live preview and reads the console, so it catches errors before you do.