Vibe Code Rescue

Supabase says "Invalid API key" on every request

You built an app with Lovable, Bolt, v0, or Cursor on top of Supabase. Now every request comes back 401 Unauthorized with {"message":"Invalid API key"}, or the app crashes on load with supabaseUrl is required. Often it worked yesterday, or works locally and dies on the deployed site. This error has exactly five common causes, and each one takes about two minutes to check.

First, see what the app is actually sending

Do this before touching anything. Open the broken page, press F12 for devtools, open the Network tab, and reload. Click a failing request to supabase.co and look at the request headers for one named apikey.

Every fix below ends the same way: confirm the correct values on one dashboard page. In Supabase, open your project, then Settings, then API. That page shows the project URL and the API keys side by side. If your app's URL and key both came from that one page, causes 1, 3, and 4 are impossible.

Cause 1: wrong key type, or a legacy key that got disabled

Supabase projects historically had two JWT keys: anon for browsers and service_role for trusted servers. Newer projects use a second generation instead: a publishable key starting with sb_publishable_... and a secret key starting with sb_secret_.... Two ways this bites AI built apps:

Cause 2: env vars exist locally but not on the deploy host

The most common cause when it works locally and 401s in production. Your .env file holds VITE_SUPABASE_URL and VITE_SUPABASE_ANON_KEY (or NEXT_PUBLIC_SUPABASE_URL and NEXT_PUBLIC_SUPABASE_ANON_KEY on Next.js). But .env is gitignored, so it never reached Vercel, Netlify, or wherever you deployed. The deployed bundle gets undefined for both, which surfaces as supabaseUrl is required or as requests with a garbage key.

  1. In your hosting dashboard, find Environment Variables (Vercel: Project Settings, Environment Variables. Netlify: Site configuration, Environment variables).
  2. Add both variables with the exact same names your code reads. The prefix matters: VITE_ and NEXT_PUBLIC_ are what expose a variable to browser code, so a var saved as plain SUPABASE_URL is invisible to the frontend.
  3. Redeploy. Not restart, redeploy. Frontend env vars are baked into the JavaScript bundle at build time. Adding a variable changes nothing until a new build runs, and this single detail explains most "I added the env vars and it still fails" threads.

Habit that prevents this permanently: keep a .env.example in the repo listing every variable name with placeholder values. It gets committed (no secrets in it), so any deploy host, collaborator, or diagnosis tool can see exactly which variables the app needs.

Cause 3: the key belongs to a different project than the URL

Each Supabase project has its own URL and its own keys, and a key from project A is invalid on project B. This happens constantly with AI builders: Lovable provisions a fresh Supabase project for you, you fork or remix an app, or you copy the key from an old project's tab while the URL points at a new one.

To check: your project URL looks like https://abcdefghij.supabase.co. That abcdefghij part is the project ref. Legacy JWT keys contain the same ref; paste the key into a JWT decoder (or the debugger at jwt.io) and compare the ref claim to the subdomain in your URL. If they differ, that is your bug. New sb_publishable_ keys do not decode this way, so use the simpler check that works for both: open Settings, then API, in the one project you actually want, and copy the URL and the key from that single page in one sitting. Never mix values from two tabs.

Cause 4: the key is truncated, quoted, or has a trailing newline

Legacy anon keys are long JWTs, over 200 characters. Things that mangle them:

To check: in the Network tab, copy the exact apikey header value the browser sent and paste it next to the key on your Settings, API page in a text editor. Compare lengths and endings character by character. If they differ at all, re-paste the key carefully and redeploy.

Cause 5: your free tier project is paused

Supabase pauses free tier projects after about a week without activity. A paused project refuses all API requests, which the frontend can surface as failed fetches or auth errors, and it commonly hits apps that were built in a burst and then left alone. Open the Supabase dashboard: a paused project shows a paused banner and a restore button on its home page. Click restore, wait a few minutes for it to come back, and reload your app. If the app matters, open it once a week or upgrade the project so it stays awake.

Still stuck?

Run the instant diagnosis. Paste your public repo URL into the form and an automated clean-room check reports what is broken: install, build, missing env config, and render, with the exact blocker named, in minutes, free. It catches the missing env var and truncated key cases directly. Keys and project settings live in your Supabase dashboard rather than the repo, so for those also paste the failing request from your Network tab (without the key value) into the issue and I will look the same day. Private repo or zip? Email works too.

Get an instant free diagnosis

Or email me instead. Fixes with 24 hour turnaround start at $95. Prefer self-serve? The $5 instant diagnosis on Apify checks your repo privately, no public issue needed.