"Invalid API key" or Undefined Env Vars on Vercel: How to Fix It

Quick answer: Your app works locally but on Vercel you get "Invalid API key" or undefined environment variables? Here's how Vercel env vars work and how to fix them.

The error

Common variants:

Error: supabaseUrl is required.
AuthApiError: Invalid API key
OpenAI API error: 401 Incorrect API key provided: undefined

Or process.env.MY_KEY is simply undefined in production.

Why it happens

Fixes

1. Add the variables in Vercel

Vercel → Project → Settings → Environment Variables. Add each key, tick the environments that need it, then redeploy (Deployments → ⋯ → Redeploy). Or use the CLI:

vercel env add NEXT_PUBLIC_SUPABASE_URL production
vercel env pull .env.local   # pulls the Development values (add --environment=production for prod)

2. Use the right prefix for browser code

// Next.js: inlined at BUILD time, visible in the browser
const url = process.env.NEXT_PUBLIC_SUPABASE_URL!;

// Vite
const url = import.meta.env.VITE_SUPABASE_URL;

Public prefixes are baked in at build time, which is another reason a redeploy is required.

3. Keep secrets server-side

Secret keys (SUPABASE_SERVICE_ROLE_KEY, OPENAI_API_KEY, STRIPE_SECRET_KEY) must not get a public prefix. Anything with NEXT_PUBLIC_ or VITE_ ends up in the JavaScript sent to every visitor. Use secrets only in Route Handlers, Server Actions, or API routes:

// app/api/chat/route.ts
export async function POST(req: Request) {
  const key = process.env.OPENAI_API_KEY; // server only
  // ...
}

4. Fail fast with a clear message

function requireEnv(name: string) {
  const v = process.env[name];
  if (!v) throw new Error(`Missing env var: ${name}`);
  return v;
}

Note: for NEXT_PUBLIC_ variables in client code, reference them literally (process.env.NEXT_PUBLIC_X). Dynamic lookups like process.env[name] aren't inlined in the browser.

5. Check the value itself

Re-copy the key from the provider dashboard. Remove quotes and trailing spaces. Make sure it's the key for the right project (e.g. the Supabase anon or sb_publishable_… key for the client, never the service role or sb_secret_… key).

FAQ

I added it but it's still undefined. Did you redeploy? Is it ticked for Production? Is the Supabase anon key safe to expose? It's designed to be public, but only if Row Level Security is enabled on your tables.

Still stuck? Paste your exact error into the free Error Fixer to get a plain-English cause, the fix, and a prompt to paste back into your AI tool.

Get the free "10 Prompts That Fix Broken AI Code" pack

Join the FixKit AI newsletter: one short email a week with real errors from Cursor, Lovable, Bolt & Replit users and how to fix them. Unsubscribe anytime.

Newsletter signup powered by beehiiv. We only use your email to send the newsletter.