DEV Community

Fredrik
Fredrik

Posted on

The five reasons a Next.js app works locally and fails on Vercel

Most failed Vercel deploys I have looked at come down to the same five mistakes. None of them show up on your laptop, which is exactly why they are annoying. Here they are, with the fix for each.

1. Env variables that only exist on your machine

Your code reads process.env.STRIPE_SECRET_KEY, your .env.local has it, the Vercel project does not. The error often points somewhere unrelated, like an SDK throwing on an undefined key.

Fix: keep a committed .env.example with every variable name and an empty value, and check the Vercel project settings for each name in every environment. Preview is the scope people forget. Also check your .gitignore: a rule like .env* hides .env.example too, so add !.env.example at the end.

2. Imports that resolve on macOS and fail on Linux

import Header from './components/Header' works when the file is header.tsx, because macOS and Windows ignore letter case. Vercel builds on Linux, which does not.

Fix: match the casing exactly. To rename a file by case in git, use git mv header.tsx Header.tsx, otherwise git may not notice the change.

3. Node only packages in Edge code

fs, net, pg, ioredis and friends cannot run in the Edge runtime, and the bundler follows every static import, including the ones inside your middleware.

Fix: set export const runtime = 'nodejs' on that route, or switch to an HTTP based client such as @upstash/redis.

4. A lockfile out of sync with package.json

Frozen installs fail with ERR_PNPM_OUTDATED_LOCKFILE or the npm equivalent. A dependency pinned to latest can never be satisfied by a frozen lockfile.

Fix: pin real versions, regenerate the lockfile with the same package manager version Vercel uses, and commit it. Avoid turning off the frozen lockfile, it only hides the drift.

5. Prisma client not generated on Vercel

The generated client is gitignored and nothing runs the generator during install, so the build imports a client that does not exist.

Fix: add prisma generate to the postinstall script in package.json.

Checking all five automatically

I got tired of finding these one failed deploy at a time, so I built DeployDoctor. Paste a public GitHub repo and it reads the code through the GitHub API, with no clone and no code execution, and checks all five plus hardcoded secrets, build config and Supabase setup. Every finding names the file and line and gives a fix you can copy. It is free for public repos, three scans a day.

If you want it on every pull request, there is a GitHub Action that runs the same checks before Vercel builds and annotates the findings on the changed files. It is free on public repos with no token.

Which deploy failures have you hit that are not on this list? I am collecting them for the next checks.

Top comments (0)