Why your environment variables aren't working — 3 common causes

A familiar pain: works locally, you paste a key — and suddenly undefined. Or you deploy, and in production the app can't see the variable.
Don't rush to rewrite code. Nine times out of ten it's one of three causes. And all three fix in a minute.
The symptom
It always looks similar. In your code you read process.env.MY_KEY (or via import.meta.env) and get undefined. The app complains "no key," even though you definitely set it. Let's go from the most common.
Cause 1. You didn't restart
The most common — and the most annoying. You added the variable to the .env file, but the program never noticed.
Why: environment variables are read once, at startup. Add a new one while the server is running, and it doesn't know about it.
How to check: stop the dev server (Ctrl+C) and see whether it's still running from the old start.
How to fix: restart the server. And if it's a build (Next.js, Vite, and such) — rebuild the project. The variable shows up only after a fresh start.
Cause 2. .env never reached production
Works locally, not in production. A classic.
Why: the .env file only lives on your computer. It's (rightly) kept out of git — otherwise secrets leak. And since it's not in the repository, it doesn't reach the server on deploy either. Production genuinely doesn't know your variables.
How to check: go to your host's settings (Vercel, Netlify, Railway — wherever you deploy) into the Environment Variables section. Empty? There's your answer.
How to fix: add each variable there by hand, through the host's panel. Name for name, value for value. Then redeploy. If the deploy still fails — see the neighboring breakdown why your deploy fails.
Cause 3. Prefix and client vs server
Subtle, but common. The variable exists, yet in the browser it's still undefined.
Why: secrets are visible only on the server by default. For a variable to reach code in the browser, its name has to start with a special prefix. In Next.js that's NEXT_PUBLIC_, in Vite — VITE_. Without the prefix, the variable lives on the server only — and that's protection, not a bug.
How to check: are you reading the variable in code that runs in the browser? Then look at the name.
How to fix: need it on the client — add the prefix (NEXT_PUBLIC_..., VITE_...) and restart. But be careful: anything with a public prefix is visible to everyone in the browser. A secret key must not go there — its place is on the server (see how to store keys).
Why can't I commit .env to git?
Because anything that lands in git is easy to pull back out — especially if the repo is public. Paste a key into .env, commit, push — and bots find it within minutes. That's why .env goes into .gitignore, and production values are entered through the host's panel. If a key already leaked — don't hide it, revoke the old one and create a new one right away.
The variable is there but still undefined — what else?
Run through the small stuff: a typo in the name (API_KEY vs API_kEY — case matters); extra quotes or spaces in the value; the wrong file (.env.local vs .env); or the variable read before it had a chance to load. If the key fails specifically with an API service — there's a separate checklist: why your API key isn't working.
Short story-lessons, an agent simulator and daily practice — in our mobile app. Free.





