Your AI coding agent wired up an environment variable, process.env.STRIPE_KEY or process.env.API_URL, exactly the way a thousand tutorials it trained on do it. It ran fine in whatever sandbox the agent used to preview the app. You build for production and either the whole app white-screens with Uncaught ReferenceError: process is not defined, or worse, it loads fine and the key is silently undefined, so the feature that depends on it just quietly does nothing.
Why this happens
Vite-based apps (which is what Cursor, Claude Code, Lovable, v0, and Bolt all scaffold when you ask for a React or Vue frontend) don’t inject the Node.js process global into the browser bundle. process.env is a Node.js runtime object; it has never existed in a browser, and Vite doesn’t polyfill it. Webpack-based setups like Create React App did paper over this for years, by statically replacing process.env.REACT_APP_X at build time, so a huge share of the tutorials and Stack Overflow answers an agent has trained on use that exact pattern. The agent reproduces it faithfully in a Vite project, where the equivalent mechanism doesn’t exist.
Vite’s actual mechanism is import.meta.env, and it comes with an additional, deliberate restriction: only variables whose name starts with VITE_ get exposed to client code. Vite scans your .env files and statically replaces import.meta.env.VITE_SOME_KEY at build time; anything not prefixed VITE_, like a plain DATABASE_URL or STRIPE_SECRET_KEY, stays server-side only, on purpose, so a backend secret an agent happens to reference in the same .env file can’t leak into the client bundle it ships to every visitor’s browser.
That’s why this bug has two different faces. If the agent wrote raw process.env.X, the browser doesn’t know what process is at all, and you get a hard crash, process is not defined, the moment that line executes. If the agent correctly used import.meta.env.X but forgot the VITE_ prefix, there’s no crash: Vite just replaces the reference with undefined, silently, and whatever depended on that value fails downstream in whatever way an undefined string does: an API call to undefined/endpoint, an empty auth header, a component that renders nothing.
How to tell if this is your problem
- Check the browser console first.
process is not definedis unambiguous: search your source forprocess.envand you’ve found every instance. - If there’s no crash but a feature silently fails, log the value right before it’s used (
console.log(import.meta.env.VITE_API_URL)) and check forundefined. If it’sundefinedin the built app but a real value invite dev, the prefix is the problem, not the value. - Open your
.envfile and check every variable your app actually reads client-side. Anything referenced from a component, hook, or client-side util needsVITE_on the front of its name, in both the.envfile and every place it’s read.
The fix
Rename the variable in .env:
# before
API_URL=https://api.example.com
# after
VITE_API_URL=https://api.example.com
And read it through import.meta.env, not process.env:
// before
const apiUrl = process.env.API_URL
// after
const apiUrl = import.meta.env.VITE_API_URL
Restart the dev server after any .env change. Vite only reads .env files at startup, so an edit while the server is still running won’t take effect until you restart it, and an agent that edits the file and immediately tests can end up “confirming” a fix that hasn’t actually loaded yet.
How to avoid this next time
Keep true secrets, database URLs, third-party API keys your frontend should never see, unprefixed, so they never make it into the client bundle in the first place. Only prefix VITE_ on values that are safe to ship to every visitor’s browser, like a public API base URL or a publishable (not secret) Stripe key. If your agent writes process.env anywhere in a Vite project, treat it as a mismatch on sight: it’s either about to crash or about to silently return undefined, and neither shows up as a red squiggly line while you’re reading the code.
Comments
Sign in to join the conversation.
No comments yet — be the first.