matevalidate.com Scan your site free →

← All guides

Your environment variables are undefined in production

The deployed app crashes on load, and the console points at configuration:

Uncaught Error: supabaseUrl is required.
TypeError: Failed to construct 'URL': Invalid URL
Uncaught TypeError: Cannot read properties of undefined (reading 'VITE_API_URL')

Locally, everything works. The variable is set — you can see it in your .env file. And yet production says undefined.

The one fact that explains all of it

Frontend environment variables are not read when the app runs. They are pasted into the code when the app is built.

When the build runs, every import.meta.env.VITE_API_URL in your source is replaced with the literal string the build machine had at that moment. The deployed site is static files; there is no server reading variables when a visitor arrives. Three consequences, each of which is one of the classic failures:

  1. Your local .env never travels. It is ignored by git (correctly), so the host's build machine has never seen it. The values must be entered in the host's own settings.
  2. Setting a variable without rebuilding changes nothing. The old value — or the undefined — is already baked into the deployed JavaScript. Every change to variables needs a new deploy after it.
  3. The prefix is a gate, not a convention. Vite only exposes variables starting with VITE_, Next.js with NEXT_PUBLIC_, Create React App with REACT_APP_. A variable named API_URL is invisible to the frontend build on purpose — the prefix is you saying "this may be public".

Fix it on your host

The steps are the same everywhere; only the menu differs.

NetlifySite configuration → Environment variables → add each variable → Deploys → Trigger deploy.

VercelSettings → Environment Variables → add for the environments that need it (Production at least) → redeploy from the Deployments tab.

Lovable / Bolt — the platform manages variables with the integration; the usual failure is a remix or duplicate of a project, where code arrives but values do not. Re-connect the integration (Supabase above all) in the copy, then publish again. More in the Bolt deploy guide.

Then verify the names character by character against what the code reads. VITE_SUPABASE_ANON_KEY and VITE_SUPABASE_KEY are different variables, and an AI that generated one name in code and another in documentation has done exactly this to a lot of people.

The security line, because this is where it gets crossed

The VITE_/NEXT_PUBLIC_ prefix means public. Anything with it ships to every visitor's browser, readable in the bundle.

Hand it to the AI

Paste this to the AI that built your app

My deployed app fails with an environment-variable problem. The console error
is:

[paste the exact error]

List every environment variable this codebase reads (search for
import.meta.env, process.env.NEXT_PUBLIC, process.env.REACT_APP). For each:
its exact name, whether it is safe to be public, and the value's source. Tell
me which are missing for production on [Netlify/Vercel/Lovable/Bolt] and the
exact steps to set them there. If any secret key (service role, sk_...) is
read by frontend code, flag it and move that call server-side instead.

Prove it

After setting the variables and redeploying, open the site in a private window with the console open: the startup errors must be gone. If requests now reach your backend but come back 401/403, the variables are fine and you have moved on to a permissions problem — likely RLS.

Questions people also ask

I set the variable on Netlify/Vercel and it is still undefined. Why?

Frontend variables are inlined into the JavaScript when the site is built. A value added after the last build is not in the deployed code — trigger a new deploy and it will be.

Why does the variable work locally but not deployed?

Locally it comes from your .env file, which is (rightly) not committed and never uploaded. The host builds from your repository, where that file does not exist, so the host needs the values entered in its own settings.

Is it safe that my Supabase anon key is visible in the built code?

Yes — the anon key is designed to be public, and your data is protected by row-level security policies, not by hiding the key. What must never be in frontend code is a service-role key, an OpenAI/Stripe secret key, or any credential whose leak grants real power.