Fix · Works locally, fails in production: missing env vars and secrets

Vercel environment variable undefined in production, set in dashboard

The variable shows in your Vercel project settings and the code works locally, but in production it reads as undefined. The usual causes are a deployment built before the variable was saved, a variable scoped to the wrong environment, and public values the build did not inline for the browser.

Likely causes, most common first

Cause 1 · in 1 of 8 matching cases

Browser 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.

Cause 2

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.

Cause 3

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.

Cause 4

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.

Check and fix it, step by step

  1. List what Production actually has

    From a linked project, list the variables for each environment and compare them. A variable listed under preview but not under production explains why preview works and production fails.

    vercel env ls production
    vercel env ls preview

    Docs: vercel.com →

  2. Confirm the live deployment was built after the change

    Environment variable changes are not applied to previous deployments. If you saved the value after the current production deployment was created, that deployment does not have it.

    Docs: vercel.com →

  3. Check whether the failing read runs on the server or in the browser

    Server code such as a Next.js Route Handler can read unprefixed variables. Browser code only receives the NEXT_PUBLIC_ values that the build inlined into the bundle. The browser cannot access an email API key or a database connection string without the prefix, so read it on the server.

    // app/api/send/route.ts (server): unprefixed works here
    const key = process.env.EMAIL_API_KEY
    // client component: needs the prefix, inlined at build time
    const site = process.env.NEXT_PUBLIC_SITE_URL

    Docs: nextjs.org →

  4. Replace dynamic lookups with direct references

    Next.js does not inline lookups through a variable. Write the full property access in client code.

    // not inlined
    const env = process.env
    env.NEXT_PUBLIC_SITE_URL
    // inlined at build time
    process.env.NEXT_PUBLIC_SITE_URL

    Docs: nextjs.org →

  5. Create a new production deployment

    Once the variable is scoped to Production, push a commit to the production branch or run vercel --prod. Public variables are fixed at build time, so they need this fresh build too.

    vercel --prod

    Docs: vercel.com →

Quick check: vercel env ls production # is it listed, and was the live deployment created after it was added?

How often this shows up in our data

8 of the 344 verified cases from the last 12 months in our data match this symptom (2.3%). The most common cause was “Browser code reads a variable the build did not expose” (1 of 8); 7 didn't show which cause. How we collect and verify cases.

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.


Sources

Every cause and step above was checked against these pages on 1 Oct 2026.

The broader pattern

This is one symptom of a wider failure pattern: Works locally, fails in production: missing env vars and secrets. The guide covers every cause we see for it, on any stack.

Get a heads-up when Vercel breaks something

Vercel

Leave your email and we'll let you know when something big changes for Vercel. Unsubscribe any time by replying. Gemmein Limited. Research terms · Privacy

← All fixes