Fix: Vercel Deployment Failed - Common Causes and Solutions
Part of: Docker, DevOps & Infrastructure
Quick Answer
Fix Vercel deployment failures caused by build errors, environment variables, serverless function limits, and dependency issues with step-by-step solutions.
The Error
Your Vercel deployment fails with one of these messages in the build log:
Error: Command "npm run build" exited with 1Error: Serverless Function has exceeded the unzipped maximum size of 250 MBError: No Output Directory named "out" found after the Build completedThe deployment shows a red status in the Vercel dashboard, and your site isn’t updated.
Why This Happens
Vercel builds your project on an ephemeral Linux machine, then packages the output for either a static CDN edge or a serverless runtime. Every build starts in a clean working directory (though node_modules and a handful of other caches are restored from previous successful runs on the same branch). That means environment differences your local machine hides become visible at build time: case-sensitive imports that work on macOS fail on Linux, system fonts that exist in your dev container don’t exist on Vercel, native dependencies compiled against your local libc don’t match Vercel’s, and .env.local values that drive your npm run build step are simply not present.
The second source of failure is the constraint surface Vercel imposes. Serverless functions have a 250 MB unzipped size cap (Hobby and Pro), edge functions have a 1 MB cap in the V8 runtime, build memory tops out at 8GB on Pro, individual serverless function execution is capped at the plan’s max duration, and the entire deployment has a per-build time limit. None of these limits are enforced locally, so a project that runs fine in next dev can fail at deploy because a single page imports aws-sdk and pushes the function payload over the size limit. The error often points at the symptom (function too large) rather than the cause (a stray import).
The third class of failure is build cache poisoning. Vercel restores node_modules, framework caches (.next/cache), and Turborepo’s task cache across builds on the same branch. When the cache contains a corrupt or stale artifact — usually after a Node version change, a lockfile rewrite, or a framework update — every subsequent build inherits the bad state until the cache is cleared. The symptom is a build that fails on Vercel but passes locally, and the fix is the “Redeploy without Build Cache” option in the deployment menu. Skipping this step and hunting for code bugs that don’t exist wastes hours.
Diagnostic Timeline
Use this order. Most Vercel build failures resolve at minute 2 once you’ve read the actual error and confirmed it’s not a cache issue.
- Minute 0 — Open the build log and scroll to the first error. Vercel’s UI sometimes shows the last error first; the actual cause is the earliest red line. Filter the log to “Build” to skip the install logs.
- Minute 1 — Reproduce locally with the same Node version. Read the “Installing Node.js X” line in the build log, switch to that version with
nvm use X, deletenode_modules, runnpm ci && npm run build. If it fails locally with the same error, it’s a code or config issue; if it passes locally, it’s an environment or cache issue. - Minute 2 — Trigger a redeploy without build cache. From the failing deployment, click “Redeploy” and uncheck “Use existing Build Cache.” If the next build succeeds, you had cache poisoning and the original code is fine.
- Minute 3 — Audit environment variables in the failing scope. Settings > Environment Variables. Confirm each variable your build reads is present in the Production scope (or Preview if it’s a preview deploy). A missing
DATABASE_URLcausesnext buildto crash with a connection error that looks like a code bug. - Minute 4 — Check serverless function sizes in the deployment summary. The “Functions” tab of the deployment page lists every function with its size. Anything close to 250 MB will eventually push over after a single dependency bump.
- Minute 5 — Look at DNS verification on custom domains. If the deployment succeeded but the domain returns 404 or “Domain not verified,” the DNS records weren’t updated. Settings > Domains shows verification state per domain.
- Minute 6 — Run
vercel buildlocally. Install the Vercel CLI (npm i -g vercel) and runvercel buildin the project root. This uses Vercel’s actual build pipeline locally, which catches framework-detection mismatches andvercel.jsonerrors thatnpm run builddoesn’t see.
Fix 1: Fix Build Command Errors
The most common failure. Check your build output in the Vercel dashboard under Deployments > [failed deployment] > Build Logs.
Common issues:
# TypeScript errors that you ignored locally
Type error: Property 'x' does not exist on type 'y'
# ESLint errors treated as warnings locally but errors in CI
error Unexpected console statement no-consoleYour next.config.js or framework config might treat warnings as errors in production:
// next.config.js
module.exports = {
eslint: {
ignoreDuringBuilds: true, // Skip ESLint during build
},
typescript: {
ignoreBuildErrors: true, // Skip type checking (not recommended)
},
};A better approach is to fix the actual errors. Run the same build command locally:
npm run buildPro Tip: Add
"build:check": "tsc --noEmit && eslint . && next build"to your package.json and run it locally before pushing. This catches exactly what Vercel will catch.
Fix 2: Configure Environment Variables
Environment variables set in your local .env file don’t exist on Vercel. Add them in the Vercel dashboard under Settings > Environment Variables:
DATABASE_URL=postgresql://...
NEXT_PUBLIC_API_URL=https://api.example.com
SECRET_KEY=your-secretKey points:
- Variables prefixed with
NEXT_PUBLIC_are exposed to the browser in Next.js - Variables without the prefix are only available server-side
- Set different values for Production, Preview, and Development environments
- Vercel automatically sets
VERCEL,VERCEL_ENV,VERCEL_URL, and other system variables
If your build accesses environment variables at build time, they must be present during the build. Runtime-only variables work for serverless functions but not for static generation.
Check if a variable is missing:
// This crashes the build if DB_URL is undefined
const db = new Database(process.env.DB_URL); // undefined
// Guard against missing variables
if (!process.env.DB_URL) {
throw new Error('DB_URL environment variable is required');
}Fix 3: Fix Serverless Function Size Limits
Vercel limits serverless functions to 250 MB unzipped. If your API routes or server-side rendered pages bundle too many dependencies, you hit this limit:
Error: Serverless Function has exceeded the unzipped maximum size of 250 MBReduce function size:
// next.config.js
module.exports = {
experimental: {
outputFileTracingExcludes: {
'/api/*': ['./node_modules/@swc/core-linux-x64-gnu'],
},
},
};Move heavy dependencies to Edge Functions where appropriate:
// pages/api/light-endpoint.js
export const config = {
runtime: 'edge', // Much smaller size limit applies differently
};Check which dependencies are bloating your functions:
npx @next/bundle-analyzerCommon culprits: aws-sdk (use @aws-sdk/client-s3 instead), sharp (Vercel provides it), prisma (use the data proxy).
Fix 4: Set the Correct Node.js Version
Vercel uses a specific Node.js version that might differ from your local setup. Specify it in your project settings or package.json:
{
"engines": {
"node": "20.x"
}
}Or in Vercel project settings under Settings > General > Node.js Version.
Mismatched versions cause issues with:
- Native modules compiled for a different Node.js version
- Syntax features not available in the target version
- npm/yarn lockfile incompatibilities
Check the build log for the Node.js version being used:
Installing Node.js 18.xFix 5: Fix Monorepo Root Directory
If your project is in a monorepo subdirectory, Vercel needs to know where to find it:
monorepo/
├── packages/
│ ├── web/ ← Your Vercel project
│ ├── api/
│ └── shared/
├── package.json
└── turbo.jsonSet the Root Directory in Vercel: Settings > General > Root Directory to packages/web.
For Turborepo or Nx monorepos, configure the build command:
# Vercel build command
cd ../.. && npx turbo run build --filter=webCommon Mistake: Setting the root directory but forgetting that dependencies from the monorepo root
node_modulesaren’t available. UseinstallCommandoverride:cd ../.. && npm install && cd packages/web.
Common monorepo issues:
- Shared packages not being built before the web app
- Workspace protocol (
workspace:*) not resolved during Vercel install - Missing
.npmrcor.yarnrc.ymlconfiguration
Fix 6: Fix Edge Function Issues
Edge Functions have stricter limits than regular serverless functions:
Error: Edge Function has hit the maximum size limit (1 MB)Edge Functions can’t use Node.js APIs like fs, path, or child_process. They run in the V8 runtime:
// This fails in Edge Functions
import fs from 'fs'; // Not available
// Use Web APIs instead
export const config = { runtime: 'edge' };
export default async function handler(request) {
const data = await fetch('https://api.example.com/data');
return new Response(JSON.stringify(await data.json()));
}If your function needs Node.js APIs, use the default serverless runtime instead of edge.
Fix 7: Fix Dependency Installation Failures
Vercel installs dependencies based on your lockfile. If it’s corrupted or outdated:
npm ERR! ERESOLVE unable to resolve dependency treeFix steps:
# Regenerate lockfile locally
rm -rf node_modules package-lock.json
npm install
git add package-lock.json
git commit -m "Regenerate lockfile"
git pushFor peer dependency conflicts, either resolve them or use the --legacy-peer-deps flag:
{
"scripts": {
"vercel-install": "npm install --legacy-peer-deps"
}
}Set the install command in Vercel settings to npm run vercel-install.
If using private packages, add an NPM token:
# Vercel environment variable
NPM_TOKEN=npm_xxxxxCreate .npmrc in your project:
//registry.npmjs.org/:_authToken=${NPM_TOKEN}Fix 8: Fix Framework Detection
Vercel auto-detects your framework (Next.js, Astro, Vite, etc.) and sets build commands accordingly. If detection fails:
Error: No framework detectedOverride in vercel.json:
{
"framework": "nextjs",
"buildCommand": "npm run build",
"outputDirectory": ".next"
}Common framework settings:
| Framework | Build Command | Output Directory |
|---|---|---|
| Next.js | next build | .next |
| Astro | astro build | dist |
| Vite/React | vite build | dist |
| CRA | react-scripts build | build |
| Nuxt | nuxt build | .output |
If your output directory doesn’t match what Vercel expects, the deployment succeeds but shows a 404:
{
"outputDirectory": "dist"
}Still Not Working?
Check build memory limits. Vercel’s free tier has limited build memory. If your build runs out of memory, optimize it or upgrade your plan. Look for
JavaScript heap out of memoryin build logs.Review Vercel’s system status. Intermittent build failures might be platform issues. Check the official status page before assuming the problem is yours.
Test with
vercel buildlocally. Install the Vercel CLI (npm i -g vercel) and runvercel buildto reproduce the deployment environment locally.Check API route configuration. API routes must export a default function. Missing exports cause silent deployment failures.
Look for large static assets. Images, videos, or data files in your public directory count toward deployment size limits. Use external CDNs for large assets.
Verify Next.js configuration. Invalid
next.config.jsoptions can cause builds to fail without clear error messages. Test with a minimal config.Force a redeploy without the build cache. From the failing deployment, click the three-dot menu and choose “Redeploy” with “Use existing Build Cache” unchecked. Cache poisoning after a Node version bump or framework upgrade is the single most common cause of a build that fails on Vercel but succeeds locally.
Audit environment variables across scopes. Variables set in the Development scope only are unavailable to Production and Preview deployments. Settings > Environment Variables shows the scope tags per variable. A
DATABASE_URLin Development with no Production equivalent crashesnext buildon every push to main.Verify domain DNS verification. A new custom domain stuck on “Invalid Configuration” prevents traffic from reaching successful deployments — the deploy log shows green but the site returns a Vercel 404. Settings > Domains shows the required
AorCNAMErecords and the current verification state.Check function size in the deployment summary. The deployment page lists each serverless function with its unzipped size. A function at 240 MB will push past 250 MB the next time you add a dependency. Move heavy code paths to edge runtime where they fit, or split a monolithic API route into per-endpoint files so the bundle isn’t shared.
Inspect for missing environment variables at build time vs runtime. Static-generation (
getStaticProps,generateStaticParams) runs at build time and needs build-time variables. Server actions and API routes run at request time and need runtime variables. Mixing the two scopes means a variable that’s “set” in the UI is still undefined to the code that uses it.Look at the deployment’s “Functions” region. A function pinned to a region without your database (Edge vs the default
iad1) adds 100+ ms of latency to every cold start and can time out at deploy if the function reaches out to a backend during initialization. Set the region explicitly invercel.jsonto match your data source.
Solo developer based in Japan. Every solution is cross-referenced with official documentation and tested before publishing.
Was this article helpful?
Related Articles
Fix: Gunicorn Not Working — Worker Timeout, Boot Errors, and Signal Handling
How to fix Gunicorn errors — WORKER TIMEOUT killed, ImportError cannot import app, worker class not found, connection refused 502 behind nginx, graceful reload not working, and sync vs async worker selection.
Fix: ONNX Not Working — Conversion Errors, Runtime Provider Issues, and Dynamic Shape Problems
How to fix ONNX errors — torch.onnx.export unsupported operator, ONNX Runtime CUDA provider not found, InvalidArgument input shape mismatch, dynamic axes not working, IR version mismatch, and opset version conflicts.
Fix: Uvicorn Not Working — Worker Errors, Reload Issues, and Production Deployment
How to fix Uvicorn errors — Address already in use port binding, reload not detecting changes, SSL certificate errors, worker class with gunicorn, WebSocket disconnect, graceful shutdown, and proxy headers behind nginx.
Fix: Coolify Not Working — Deployment Failing, SSL Not Working, or Containers Not Starting
How to fix Coolify self-hosted PaaS issues — server setup, application deployment, Docker and Nixpacks builds, environment variables, SSL certificates, database provisioning, and GitHub integration.