Your AI coding agent wired up an analytics key, a Stripe publishable key or an API URL. It reads process.env.API_URL in a component, and in the browser the value is undefined. The .env file is right there, the server logs show the value, and the page still behaves as if the variable does not exist.
The cause is how Next.js decides which variables the browser may see, and the fix is a prefix plus a rebuild.
Why this happens
The Next.js docs say it plainly: variables without the NEXT_PUBLIC_ prefix “are only available in the Node.js environment, meaning they aren’t accessible to the browser.” The browser runs in a different environment from your server, so a plain process.env.API_URL in a Client Component has nothing to read.
To expose a value to the browser, Next.js inlines it at build time. In the docs’ words, it replaces references to process.env.[variable] in the JavaScript bundle with a hard-coded value, but only for variables prefixed with NEXT_PUBLIC_.
Agents trained on plain Node scripts and on other frameworks often write the bare name. They also tend to get three related things wrong:
- Dynamic lookups are not inlined. The docs show that
process.env[varName]andconst env = process.env; env.NEXT_PUBLIC_Xare not replaced, even with the right prefix. Only the literal formprocess.env.NEXT_PUBLIC_Xworks in browser code. - The value freezes at build time. After the build, per the docs, your app “will no longer respond to changes to these environment variables.” Editing the variable on your host and redeploying without a rebuild keeps the old value.
.envfiles undersrc/are ignored. The docs say Next.js loads.envfiles from the project root only, not from the/srcfolder.
How to tell if this is your problem
- Find the failing read. Search the code for
process.env.inside any file that starts with'use client', or in any code that runs in the browser. - Check the name. If it has no
NEXT_PUBLIC_prefix, that is the cause. - If it does have the prefix and is still undefined, look for
process.env[...]or a copiedprocess.envobject, then check that the.envfile is in the project root and that the value existed when you last rannext build.
The fix
Rename the variable in your .env file and in the code:
NEXT_PUBLIC_API_URL=https://api.example.com
const url = process.env.NEXT_PUBLIC_API_URL
Then restart next dev, or run next build again for production. On a host such as Vercel or Netlify, set the variable in the host’s settings before the build runs, then trigger a new build, not just a redeploy of the old one.
Keep secrets on the server
Anything with the NEXT_PUBLIC_ prefix is written into JavaScript that every visitor downloads. Use it for values that are meant to be public, such as an analytics ID or a publishable key. Do not add the prefix to a secret key just to make an error go away. Instead, read the secret in a Server Component or Route Handler and pass the browser only the result.
If you need a value that changes after the build
The docs describe a runtime route: read the variable on the server during dynamic rendering. Calling await connection() from next/server before reading process.env.MY_VALUE opts the component into dynamic rendering, so the value is evaluated at request time. The docs note this lets one Docker image be promoted through several environments.
How to avoid this next time
Tell the agent up front: “In this Next.js app, browser code can only read variables named NEXT_PUBLIC_*, written as a literal process.env.NEXT_PUBLIC_NAME. Secrets stay in server code and are never given that prefix.” In review, search the diff for process.env in client files and confirm each name carries the prefix.
Comments
Sign in to join the conversation.
No comments yet — be the first.