Dev.to WebDev 🛠 Dev 👁 0 📖 2 min read

Vite env variable undefined in production? Set VITE_ before the build

Your production app throws one of these: import.meta.env.VITE_SUPABASE_URL is undefined supabaseUrl is required Cannot read properties of undefined Vite replaces import.meta.env values when the app is built, and

Your production app throws one of these:

import.meta.env.VITE_SUPABASE_URL is undefined
supabaseUrl is required
Cannot read properties of undefined

Vite replaces import.meta.env values when the app is built, and only variables that start with VITE_ reach browser code. Set those VITE_ variables on the host before the build runs, then rebuild. Keep anything secret out of VITE_ variables entirely.

I see this constantly in Lovable and Bolt apps the first time they leave the builder and land on Vercel, Netlify, or Cloudflare.

Why it happens

  1. The variable was added after the build. Values are written into the bundle at build time, so adding a variable on the host does nothing until you rebuild.
  2. Missing VITE_ prefix. Variables without that prefix are not exposed to client code, so they read as undefined in the browser. Vite's docs: variables prefixed with VITE_ are exposed in client-side source code after bundling.
  3. Set for the wrong environment. The variable exists for preview builds but not production, or the other way round.
  4. A .env file was not deployed. A .env.local file is meant to be git-ignored, so a host building from the repository never sees it.

Find the cause

  1. Search the code for import.meta.env and list every variable it reads.
  2. In the host's settings (Vercel, Netlify, Cloudflare), check each one exists for the production environment with the exact name.
  3. Check the date of the last build against when the variables were added.

Fix 1: set the variables before building

  1. Add each VITE_ variable in the host's environment settings for production.
  2. Trigger a new deployment so the build reads them.
VITE_SUPABASE_URL=https://your-project.supabase.co
VITE_SUPABASE_PUBLISHABLE_KEY=sb_publishable_...
# never a secret key in a VITE_ variable

Fix 2: move secrets to the server

Anything secret (a Stripe secret key, a Supabase secret key, a third-party API key) belongs in a server or edge function's environment, not in a VITE_ variable. Vite compiles VITE_* values into the code the browser downloads, so anyone can read them. Vite's own docs say the same: do not put sensitive information in VITE_* variables.

Check the fix worked

Stop it coming back

  • Keep a .env.example file listing every variable the app needs, without values.
  • Fail the build when a required variable is missing, instead of failing in the browser.

Quick answers

Why does it work on Lovable and not on my host? Lovable sets the values for its own builds. A new host needs them set again, before its first build.

Are VITE_ variables hidden from users? No. They are in the downloaded JavaScript.

Full write-up with the same steps: https://stacksmesh.com/fix/vite-env-variable-undefined-in-production?utm_source=devto&utm_medium=article&utm_campaign=BR-0003

I wrote this with AI assistance and reviewed it myself.

📰 Read the original article on Dev.to WebDev

Originally published by Dev.to WebDev. Aggregated on AIWithGhost for educational purposes — full credit and traffic to the original publisher.