Your local npm run build is green. Vercel says “Build failed”. Frustrating, but the failure modes are limited. Six categories cover ~95% of real failures, and the build log tells you which one — if you know where to look. Below are the exact log strings, the diagnostic command, and the config fix for each.
Background
Vercel runs your build in a clean Linux container with the Node version you specify (or 20 LTS by default). Differences from your local machine — Node version, environment variables, file paths (case-sensitive), npm registry — are the usual culprits. The build log’s last failed step is almost always the actual cause.
How to tell
Log string → Category
"Cannot find module" → dependency or path case
"process is not defined" → missing env var (Production)
"Type error" → TypeScript stricter than local
"Killed" (no other info) → out of memory (OOM)
Build runs > 45 min then fails → timeout
"Module not found: Error: Can't ..." → dependency or alias
Same code worked yesterday, fails now → stale cache or dep drift
Quick verdict
Read the failed step in the build log first. Match to the category. Apply the matching fix below.
Before you start
- Open the failed deployment page; copy the failing log line.
- Have
package.jsonandvercel.jsonin front of you. - Know your local Node version (
node -v).
Step by step
-
Read the failed step. Failed deploy → Build Logs → search “error” or scroll to the bottom-most red block. The line right before the build process exits is usually the real cause.
-
Pin the Node version. In
package.json:
{
"engines": { "node": "20.x" },
"scripts": { "build": "astro build" }
}
Then commit and redeploy. Vercel respects engines.node exactly.
- Add the missing env var. Vercel Dashboard → Project → Settings → Environment Variables → add for Production (and Preview, if you want it there too). Then trigger a redeploy. Sample command-line via Vercel CLI:
vercel env add OPENAI_API_KEY production
# paste secret when prompted
vercel env add SITE_URL production
# https://yourdomain.com
vercel --prod # trigger fresh deploy
- Fix the type error locally first. Reproduce what Vercel sees:
npx tsc --noEmit
# if your tsconfig.json sets "strict": true, this surfaces the same errors
Either fix the code or relax tsconfig.json if the strictness was unintentional:
{
"compilerOptions": {
"strict": true,
"skipLibCheck": true,
"noUncheckedIndexedAccess": false
}
}
- Dependency / path mismatch. Lockfile drift is the classic cause:
rm -rf node_modules package-lock.json
npm install
git add package-lock.json
git commit -m "fix: refresh lockfile"
Then on Vercel, Deployments → Redeploy → uncheck “Use existing build cache” to force a clean install. Watch for case-sensitive path bugs in the log too — ./Components/Foo vs ./components/Foo works on macOS but fails on Vercel’s Linux.
- OOM (“Killed”). Reduce build memory in Astro/Next:
// astro.config.mjs
export default defineConfig({
build: {
concurrency: 1, // serial page generation
inlineStylesheets: 'never',
},
image: { service: { entrypoint: 'astro/assets/services/sharp' } },
});
Next.js: increase Node heap as a stopgap (per package.json script):
{
"scripts": {
"build": "NODE_OPTIONS='--max-old-space-size=4096' next build"
}
}
Vercel Pro raises the memory cap; Hobby has tighter limits.
- Timeout. Hobby has 45-minute hard cap. If you’re hitting it on a content site, split the build (per-locale or per-section) or upgrade to Pro. A common trick:
// astro.config.mjs — limit static pages per build
export default defineConfig({
build: { format: 'directory' },
// generate only N most recent articles per build; older live on a separate deploy
});
- Always check that the same change builds locally first. A reproducible local failure cuts cycle time:
npm ci # clean install from lockfile
npm run build # match Vercel's build command exactly
Implementation checklist
engines.nodeset inpackage.json.- Env vars exist for Production AND any other env that builds.
tsc --noEmitpasses locally.- Lockfile committed and fresh.
- Redeploys after env or config changes use “no cache” the first time.
After-launch verification
- Next deployment after the fix completes with green status.
- Build logs no longer contain the previous error string.
- Build time is within the plan’s limit.
Common pitfalls
- Reading only the bottom of the build log — the real error is often higher up.
- Adding the env var to Preview but not Production (or vice versa) and being confused.
- Committing
node_modulesto “fix” a dependency error — bloats the repo and slows builds. - Disabling TypeScript strict mode globally to dodge one error — kicks the problem down the road.
- Changing the build command to skip lint or tests “just to ship” — the failure will come back as a runtime crash.
FAQ
- How do I find the actual error message?: In the deployment view, open Build Logs and search for “error” (case-insensitive). The first match is usually the cause.
- Why does it work locally but fail on Vercel?: Different Node version, missing env var, case-sensitive paths, or a peer dependency you have locally but is not in lockfile.
- Can I rerun a build without changes?: Yes. Deployments tab → pick the failed deploy → “Redeploy” → optionally uncheck “use existing build cache”.
- My build is “Killed” — what does that mean?: Out of memory. Reduce bundle size, smaller image sets, fewer simultaneously generated pages. Or upgrade for more memory.
- Can I run Vercel’s build container locally?: Approximately, via the Vercel CLI:
vercel build --prodthenvercel deploy --prebuilt --prod. Reproduces Vercel’s environment closely.