# Vite says your env variable is undefined in production: fix it before the next build

Production works until it doesn't. Suddenly you see `import.meta.env.VITE_SUPABASE_URL is undefined`, or `supabaseUrl is required`, or a plain `Cannot read properties of undefined`.

Vite does not read environment variables at request time in the browser. It replaces `import.meta.env` values when the app is **built**, and only names that start with `VITE_` make it into client code. So the fix is almost always: set those variables on the host before the build, then rebuild. And never put a secret in a `VITE_` variable.

## Four reasons the value is missing

1. **Added after the last build.** Changing host env settings does nothing until a new build runs.
2. **No `VITE_` prefix.** Without it, the name never reaches browser code. Vite documents this: only `VITE_`-prefixed variables are exposed after bundling.
3. **Wrong environment.** Preview has it; production does not (or the reverse).
4. **`.env.local` stayed on your laptop.** Those files are git-ignored on purpose, so the host never sees them when it builds from the repo.

## Pin it down

1. Search for every `import.meta.env` use and list the names.
2. Open the host's environment settings and confirm each name exists for **production**, spelled exactly the same.
3. Compare when the variables were added with the timestamp of the last successful build.

## Fix: set `VITE_` vars, then rebuild

In Vercel, Netlify, or Cloudflare, add production values like:

```
VITE_SUPABASE_URL=https://your-project.supabase.co
VITE_SUPABASE_PUBLISHABLE_KEY=sb_publishable_...
```

Then trigger a fresh deployment so the build can read them. Publishable or anon keys that are meant for the browser can live here. Secret keys cannot.

## Secrets belong on the server

A Stripe secret, a Supabase service role key, or any third-party API secret must live in a server or edge function environment. Vite's docs warn that `VITE_*` values are bundled into source at build time. Anyone who can open your site's JavaScript can read them.

## Confirm it

- The production feature that needed the variable works.
- A free [Launch Check](https://stacksmesh.com/tools/launch-check?utm_source=hashnode&utm_medium=article&utm_campaign=BR-0003) finds no secret keys in the shipped bundle.

## Keep it from coming back

Ship a `.env.example` that lists every required name with empty values. Prefer failing the build when a required variable is missing over discovering it in the browser.

**Lovable worked, my host doesn't?** Lovable injects values for its own builds. Your new host needs the same names set before its first build.

Step-by-step on our site: [Environment variable is undefined in production](https://stacksmesh.com/fix/vite-env-variable-undefined-in-production?utm_source=hashnode&utm_medium=article&utm_campaign=BR-0003).

I wrote this with AI assistance and reviewed it myself.
