A new Gemini API key environment variable was added to .env.local but not to Vercel production. Feature worked locally and in dev but silently returned undefined in production. Root cause: variable scoped to Development only.
Impact
The Gemini-powered feature was completely non-functional in production. Users received a generic error message with no actionable information. The feature appeared fully working in all local and preview testing. The gap between apparent readiness and actual production state was invisible until end-to-end user testing.
Root Cause
GEMINI_API_KEY was added to .env.local for local development. When added to the Vercel dashboard, only the Development scope was checked — not Production or Preview. process.env.GEMINI_API_KEY returned undefined in all production builds. The error handling caught the resulting API failure but swallowed the specific cause, surfacing only a generic 'Something went wrong' message.
Resolution
Updated the GEMINI_API_KEY variable in Vercel dashboard to include the Production scope. Triggered a redeploy. Feature worked immediately. Added explicit env var validation at startup to fail loudly if required variables are absent.
Prevention Pattern
After deploying any feature that depends on a new environment variable, verify the variable exists in Vercel Production scope before marking the feature as ready. Add startup validation that throws an explicit error for any missing required variable.
Recovery
Quick fix (minutes)
Deploy risk
high
Detectable
Found after user testing in production — feature appeared to work in dev
Repeat risk
high
Prevention patterns
Ecosystem impact
Related failures
A new feature was built using the Gemini API. The API key was added to .env.local for local development. The feature was tested thoroughly — multiple input types, edge cases, error states. Everything worked. The feature was deployed to Vercel.
In production, the feature returned a generic error message on every attempt. No specifics, no hint of what failed. The build had succeeded. TypeScript reported no errors. The deployment logs looked clean.
The feature was broken in production from the moment it was deployed and would have stayed broken indefinitely without explicit user-facing testing.
Vercel environment variables have scope settings:
vercel dev (local development server)When GEMINI_API_KEY was added to the Vercel dashboard, only the Development scope was checked. The variable existed for local dev but was absent from every production build.
process.env.GEMINI_API_KEY returned undefined in production. The code passed undefined as the API key to the Gemini client, which threw an authentication error. That error was caught by a generic catch block:
try {
const result = await callGemini(prompt)
return result
} catch (error) {
return { error: 'Something went wrong.' }
}
The specific error — "API key is required" or "Invalid API key" — was discarded. The user saw a useless message. The developer saw no trace of the actual failure.
✕Vercel scope is not intuitive
Adding a variable to Vercel with Development scope does not make it available in production. The scopes are independent checkboxes. A variable added for local dev is invisible to production builds unless Production is explicitly checked.
The path from "something went wrong" to "missing production env var":
Error: GEMINI_API_KEY is not definedGEMINI_API_KEY listed with scope: Development onlyTotal time: 52 minutes. Most of it spent on steps 1-4 because the error was swallowed at the source.
The fix to prevent this class of failure from being silent: validate required environment variables at module load time and throw explicitly.
// lib/gemini.ts
const GEMINI_API_KEY = process.env.GEMINI_API_KEY ?? (() => {
throw new Error('GEMINI_API_KEY is required but not set in the environment')
})()
With this pattern, a missing variable throws at import time — not buried inside a user-facing try/catch. The error surfaces in Vercel's function logs immediately on the first invocation, with a clear message pointing directly at the cause.
For a startup validation function across all required variables:
// lib/env.ts
export function validateEnv() {
const required = ['GEMINI_API_KEY', 'NEXT_PUBLIC_BASE_URL']
const missing = required.filter(key => !process.env[key])
if (missing.length > 0) {
throw new Error(`Missing required environment variables: ${missing.join(', ')}`)
}
}
Call validateEnv() in the top-level server entry point or in API route handlers that depend on those variables.
.env.example DisciplineMaintaining a .env.example file with all required variable names (values omitted) serves as a diff target before any deployment:
# .env.example
GEMINI_API_KEY=
NEXT_PUBLIC_BASE_URL=
Before deploying a feature that adds a new env var: compare .env.example against the Vercel dashboard variable list. If a variable is in .env.example and not in Vercel Production scope, the deployment should be blocked.
The three-step sequence for any feature that requires a new environment variable:
.env.local for local development.env.exampleThe mistake is treating step 1 and step 2 as the same step. They are not. .env.local is local only. Vercel requires explicit configuration for each deployment environment.
Fix Confidence
Recovery Complexity
Pattern Family
This failure belongs to a named recurring pattern. Other failures in this family share the same root cause structure — understanding the pattern prevents multiple failure types simultaneously.
Related Failures in Same Pattern