Likely causes, most common first
Cause 1 · in 1 of 8 matching casesBrowser code reads a variable the build did not expose
In Next.js, variables without the NEXT_PUBLIC_ prefix are only available in the Node.js environment, so browser code cannot read them. Vite exposes VITE_-prefixed variables to client code through import.meta.env, and the envPrefix option changes that prefix. Public values are fixed when the build runs, so a value missing from the build environment is also missing in the browser.
How to tell: The read runs in browser code and the name lacks the NEXT_PUBLIC_ or VITE_ prefix, or the variable was not set for the environment the build ran in.
The deployment was built before you saved the variable
Vercel applies environment variable changes to new deployments only. A deployment created before you saved the value keeps running without it. If you add a missing email API key or database connection string in the dashboard, the production deployment that is already live does not change.
How to tell: You added or edited the variable after the current production deployment was created, and nothing has been deployed since.
The variable is not scoped to Production
Each variable applies only to the environments you select for it: Production, Preview, Development or a custom environment. Preview values apply to deployments from branches that are not the Production Branch. A variable set for Preview but not for Production explains a preview that works while production fails.
How to tell: vercel env ls production does not list the variable, but vercel env ls preview does.
A dynamic lookup skips build-time inlining
Next.js inlines a public variable by replacing direct references to process.env.NEXT_PUBLIC_NAME with its value. A lookup through a variable, such as process.env[name], or through an alias like const env = process.env, is not inlined. The browser gets undefined even when the variable is set correctly.
How to tell: Searching the client code finds process.env[ or const env = process.env near the failing read.
Questions
Why does it work locally but not on Vercel?
Locally, Next.js loads values from your .env* files into process.env. The default create-next-app template adds all .env files to .gitignore, so those values don't ship with your code. The deployment reads the variables configured for its environment in the Vercel project.
Do I need to redeploy after changing an environment variable on Vercel?
Yes. Vercel does not apply environment variable changes to previous deployments, so push a commit to the production branch or run vercel --prod to create a new one.
Why can't I see the value of the variable I set in the dashboard?
If it is a Secret variable, members cannot view or retrieve the value after saving, and the edit form hides the current value. The value remains available to your deployments. Variables marked Sensitive are now treated as Secrets automatically.
I changed a NEXT_PUBLIC_ variable and production still shows the old value. Why?
NEXT_PUBLIC_ values are fixed at build time, so the built app does not pick up later changes. The new value appears after a new build.