BUILD OS · DEPLOYMENT
Environment variable is undefined on Vercel but works locally
Short answer
The value exists in your local .env file but not in the deployed environment that ran the code — or it was added after the last deployment, or browser code reads a variable without the NEXT_PUBLIC_ prefix. Define it per environment (Preview and Production), redeploy, and keep secrets server-only.
Symptoms
- A page works locally and throws “undefined” or “missing API key” once deployed.
- Preview deployments fail while production works, or the opposite.
- A value is undefined only in the browser.
Why this happens
Deployed code only sees variables configured for that deployment’s environment at build or runtime. Local .env files are never uploaded. Next.js inlines only NEXT_PUBLIC_ variables into browser bundles.
Most likely causes
- The variable is not set in the hosting provider.
- It is set for Production but not Preview, or vice versa.
- It was added after the current deployment was built.
- Browser code reads a variable without the NEXT_PUBLIC_ prefix.
- A typo or stray whitespace in the name.
How to diagnose it
- List the provider’s variables per environment and compare with .env.example.
- Compare the variable’s creation time with the deployment time.
- Identify whether the failing code runs on the server or in the browser.
Fix
- Add the variable to each environment that needs it and redeploy.
- Read secrets on the server only; never add NEXT_PUBLIC_ to a secret.
- Keep .env.example (names only) in the repository so missing values are visible in review.
Verify the fix
Do not close the issue until these checks pass in the environment that matters:
- The failing flow works on the deployed URL.
- The secret value does not appear in the browser’s Sources tab.
Related Ship Passport checks
Build School’s production-readiness standard marks this area as proven only with evidence from these checks (it is Build School’s own standard, not an external certification):
- criticalEvery environment variable is set per environment
- importantLocal, preview and production are separated
- criticalNo secret ships to the browser
Common false fix
Prefixing a secret with NEXT_PUBLIC_ “to make it work” ships the secret to every visitor.
Primary references
Related pattern
Verify the current behavior before asking an agent to refactor it →
Build OS stage
Deployment · Explore Build OS →