Nurture TechnologiesNurture Tech
DevOps14 min read·September 5, 2026

Next.js Deployment Failing on Vercel

Next.jsVercelNode.jsPrisma

A Next.js build that passes locally can fail on Vercel for reasons that are not obvious from the error message. The five most common causes are environment variable misconfiguration, case-sensitive module paths, the 50MB function size limit, Prisma client not generated at build time, and Edge runtime using Node.js APIs.

Problem Summary

Vercel builds your Next.js application in a Linux environment that differs from local development in three important ways: the file system is case-sensitive, environment variables must be explicitly configured in the Vercel dashboard, and serverless functions have a 50MB bundle size limit. Each of these causes a class of build failures that only appear on Vercel, not locally.

Cause 1: Missing or Misconfigured Environment Variables

Next.js has two categories of environment variables. Variables prefixed with NEXT_PUBLIC_ are inlined into the browser bundle at build time they must be set in the Vercel dashboard before the build runs. Variables without that prefix are only available at runtime on the server and do not need to be available during the build.

If your page or component accesses process.env.NEXT_PUBLIC_SOMETHING during static generation (getStaticProps or a Server Component that renders at build time), and that variable is not set in Vercel, the build will either error or silently produce pages with undefined values.

// ❌ NEXT_PUBLIC_ variable missing in Vercel dashboard
// Renders undefined in the deployed build
export default function Page() {
  return <p>API: {process.env.NEXT_PUBLIC_API_URL}</p>;
}

// ❌ Server-only variable used in a component rendered during static build
// Will be undefined at build time even if set at runtime
export default async function Page() {
  const data = await fetch(process.env.INTERNAL_API_URL + '/data'); // undefined
}

Fix: Add variables in the Vercel dashboard

Go to your Vercel project > Settings > Environment Variables. Add each variable and select which environments it applies to (Production, Preview, Development). After adding or changing variables, trigger a new deployment environment variables are baked in at build time and do not apply retroactively.

You can import a .env file directly in the Vercel dashboard using the bulk import option. This avoids manually entering each variable and reduces the chance of typos.

Cause 2: Module Not Found (Case Sensitivity)

Windows and macOS file systems are case-insensitive by default. You can import from '@/components/Button' even if the file is named 'button.tsx' and it will work locally. Vercel runs on Linux, where the file system is case-sensitive. The same import fails in production with 'Module not found: Can't resolve @/components/Button'.

// File on disk: src/components/button.tsx

// ❌ Works locally (Windows/macOS), fails on Vercel (Linux)
import Button from '@/components/Button';

// ✓ Matches the actual filename exactly
import Button from '@/components/button';

Find all mismatched import paths

$grep -r "from '@/" src/ | grep -i "components" | sort

Compare the imported names against the actual file names on disk. Fix any casing mismatch in the import statement or rename the file to match the convention you use in imports. Committing both changes together avoids a broken intermediate state.

Cause 3: Serverless Function Size Limit (50MB)

Vercel serverless functions have a maximum bundle size of 50MB. If your application imports a large library PDF generation, image processing, a machine learning model, a large locale file directly into a page or API route, the function bundle can exceed this limit and the deployment fails.

# Vercel build error:
# Error: Serverless Function "api/generate-pdf" is 68.4 MB which exceeds
# the maximum size of 50 MB

Identify what is inflating the bundle

$ANALYZE=true npm run build

Install @next/bundle-analyzer and add it to next.config.js to get a visual breakdown of what is in each bundle. Look for unexpectedly large dependencies in the server-side bundle.

Fix: Use dynamic imports for large dependencies

// ❌ Static import bundles the library into the function at build time
import PDFDocument from 'pdfkit';

export async function POST(req: Request) {
  const doc = new PDFDocument();
  // ...
}

// ✓ Dynamic import loads the library only when the function is called
export async function POST(req: Request) {
  const { default: PDFDocument } = await import('pdfkit');
  const doc = new PDFDocument();
  // ...
}

Cause 4: Prisma Client Not Generated Before Build

Prisma generates a type-safe client from your schema at build time. If prisma generate has not run before next build, the import from '@prisma/client' will fail with 'Module not found' or throw a runtime error about the Prisma client not being initialised.

package.json
{
  "scripts": {
    "postinstall": "prisma generate",
    "build": "next build"
  }
}

// The postinstall script runs automatically after npm install on Vercel
// This ensures prisma generate always runs before next build

If your schema is in a non-default location, pass the schema path explicitly: prisma generate --schema=./path/to/schema.prisma

Cause 5: Edge Runtime Using Node.js APIs

If a file exports export const runtime = 'edge', Vercel runs it in the Edge Runtime a lightweight V8-based environment that does not include Node.js built-in modules. Importing fs, path, crypto (Node version), net, or any native module in an Edge function causes an immediate build error.

// ❌ fs is not available in the Edge Runtime
export const runtime = 'edge';

import fs from 'fs';

export async function GET() {
  const data = fs.readFileSync('./data.json', 'utf8'); // Build error
  return new Response(data);
}

// ✓ Option 1: Remove the edge runtime declaration to use Node.js runtime
// (delete the line below, or set it explicitly)
export const runtime = 'nodejs';

// ✓ Option 2: Use fetch instead of fs for remote data
export const runtime = 'edge';

export async function GET() {
  const res = await fetch('https://yourapi.com/data');
  return new Response(await res.text());
}

General Diagnosis Steps

  1. 1Run npm run build locally first if it fails locally, fix it locally before looking at Vercel
  2. 2Read the full Vercel build log the first error message is the real cause; later errors are often cascading failures
  3. 3Check environment variables open the failed deployment in Vercel, go to Settings > Environment Variables and verify every variable the build needs is present
  4. 4Verify file name casing run git ls-files | grep -i components and compare with your import statements
  5. 5Check the Vercel function size look for 'exceeded maximum size' in the build log and use bundle analysis to identify large dependencies
  6. 6Check for prisma generate if using Prisma, ensure postinstall runs prisma generate in package.json
  7. 7Check runtime declarations search for export const runtime = 'edge' and verify those files do not import Node.js built-ins

Vercel caches dependencies between builds. If you suspect a stale cache is causing the failure, open the deployment in the Vercel dashboard, click the three-dot menu, and select 'Redeploy' with 'Use existing Build Cache' unchecked.

Nurture Technologies

NEED HELP WITH YOUR STACK?

Nurture Technologies builds and maintains production-quality software for startups and businesses. If engineering problems are slowing you down, our team can help.

Talk to our team →
FAQ

FREQUENTLY ASKED QUESTIONS

Why does my Next.js build pass locally but fail on Vercel?+

The most common reasons are: environment variables set in .env.local that are not added to the Vercel dashboard, file import paths that are case-insensitive on your local machine but case-sensitive on Vercel's Linux build server, and Prisma client not being generated before the build runs. Start by checking the Vercel build log for the first error message and work from there.

How do I add environment variables to Vercel?+

Go to your Vercel project dashboard > Settings > Environment Variables. Add each variable, set its value, and choose which environments it applies to (Production, Preview, Development). After adding variables, you must trigger a new deployment environment variables are not applied to existing deployments retroactively.

What is the difference between NEXT_PUBLIC_ and regular environment variables in Next.js?+

Variables prefixed with NEXT_PUBLIC_ are inlined into the browser JavaScript bundle at build time. They are visible in the browser and must be set before the build runs. Variables without the prefix are only accessible on the server at runtime and are never sent to the browser. Use NEXT_PUBLIC_ only for values that are safe to expose publicly.

How do I fix the Vercel 50MB function size limit error?+

Use dynamic imports for large libraries instead of static imports at the top of the file. This means the library is only loaded when the function is called, not bundled into the function at build time. Install @next/bundle-analyzer to visualise what is in each bundle and identify the large dependency.

Why does Vercel show 'Module not found' for a path that exists?+

Almost always a file name casing mismatch. On Windows and macOS, imports are case-insensitive you can import from '@/components/Button' even if the file is named 'button.tsx'. On Vercel's Linux server, the import must match the exact file name including case. Check the actual file name on disk and update the import to match exactly.