NEXT_PUBLIC_ variable is undefined in production
What you see in the browserconsole.log(process.env.NEXT_PUBLIC_API_URL) // undefined
GET https://www.example.com/undefined/api/items 404 (Not Found)
NEXT_PUBLIC_ values are copied into your JavaScript when the site is built. If the variable wasn't there at build time, it stays undefined until you set it and build again.
Why it happens
Next.js replaces every process.env.NEXT_PUBLIC_... in browser code with the literal value from the environment where next build ran. After the build, the app no longer responds to changes in those variables. Next.js says this directly in its docs.
So the usual causes are: the variable was added after the last build; it is set for Preview or Development but not Production; it's in a .env file that is gitignored, so the build server never saw it; the code reads it dynamically (process.env[name] or const env = process.env), which Next.js does not inline; or one Docker image is built once and promoted to several environments.
Fix it by hand
- Check the name. It must start with exactly
NEXT_PUBLIC_, and the code must spell it the same way. - Check the environment. On Vercel, open Settings, then Environment Variables, and make sure Production is ticked for it.
- Rebuild. Trigger a new production deployment. Vercel applies changed variables only to new deployments, and because this value is baked into the JavaScript, restarting isn't enough.
- Use the literal form in code.
// inlined at build time const url = process.env.NEXT_PUBLIC_API_URL // NOT inlined, stays undefined in the browser const name = 'NEXT_PUBLIC_API_URL' const url2 = process.env[name] - One Docker image for several environments? Either build per environment with the right values, or read the value on the server at request time (a Server Component that calls
await connection()can readprocess.envat runtime) and pass it down.
Stop it happening again
- Validate required variables during the build (for example in
next.config) and fail the build if one is missing. - Keep a committed
.env.exampleand compare it with your host's Production variables before deploying. - Never put a secret behind
NEXT_PUBLIC_: anything with that prefix is readable by every visitor.
Broke After Deploy $9
Broke After Deploy finds env variables your code uses that production may not have, variables set for the wrong environment, and browser-side values that need a rebuild. Key Leaked catches the other danger: a secret behind NEXT_PUBLIC_.
- Checks your project for 37 known causes of "works locally, breaks in production" and runs your production build.
- Paste the error and it finds the cause in your code, then lists what will break next.
- Verdict first. Every finding shows the file and line, what it breaks, and the fix as a diff that is applied only with your OK.
Broke After Deploy: how it works, with examples · Install guide
Works with Claude Code, Claude.ai, Cursor, Codex and other agents that read SKILL.md files. No installs, no accounts, works offline. No-questions refund.