Skip to content

Fix: Next.js Build Failed (next build Errors and How to Fix Them)

FixDevs ·

Quick Answer

How to fix Next.js build failures — TypeScript errors blocking production builds, module resolution failures, missing environment variables, static generation errors, and common next build crash causes.

The Error

Running next build fails with one of several error types:

TypeScript error:

Type error: Property 'user' does not exist on type 'Session & Partial<SessionData>'
./src/app/dashboard/page.tsx:12:24

Module not found:

Module not found: Can't resolve '@/components/Header'
Import trace for requested module:
./src/app/layout.tsx

Static generation failure:

Error occurred prerendering page "/blog/[slug]"
Error: ENOENT: no such file or directory, open '/app/.next/server/chunks/posts.json'

Build crashes without a clear error:

> next build
info  - Compiled successfully
Error: error:0308010C:digital envelope routines::unsupported

Why This Happens

next build is stricter than next dev. It runs TypeScript type checking, static analysis, and pre-renders all static pages. Errors that are silently ignored in development cause hard failures at build time:

  • TypeScript errors — dev mode skips type checking by default; build runs tsc.
  • Missing or wrong environment variablesNEXT_PUBLIC_* variables missing at build time produce empty strings in static output.
  • getStaticProps / generateStaticParams failures — if a data source is unavailable at build time, pre-rendering fails.
  • Import path issues — path aliases not configured in both tsconfig.json and Next.js config.
  • Node.js version incompatibility — some packages require specific Node.js versions.
  • ESM/CJS conflicts — packages that use ES modules in a CommonJS context cause build crashes.

Fix 1: Fix TypeScript Errors Blocking the Build

Next.js 13+ runs TypeScript type checking during next build by default. Fix type errors or configure build behavior:

Find all TypeScript errors locally before building:

npx tsc --noEmit

This runs the type checker without emitting files — shows the same errors as next build but faster.

Common type errors and fixes:

// Error: Object is possibly 'undefined'
const user = session.user; // session.user might be undefined
console.log(user.name);    // TS error

// Fix — add a null check
if (session.user) {
  console.log(session.user.name);
}
// Or use optional chaining
console.log(session.user?.name);
// Error: Type 'string | undefined' is not assignable to type 'string'
function greet(name: string) { return `Hello, ${name}`; }
greet(process.env.USER_NAME); // process.env always returns string | undefined

// Fix — assert or provide a default
greet(process.env.USER_NAME ?? 'Guest');
// Or add a runtime check
if (!process.env.USER_NAME) throw new Error('USER_NAME is required');
greet(process.env.USER_NAME);

Skip type checking in build (emergency escape hatch):

// next.config.js — not recommended for production
module.exports = {
  typescript: {
    ignoreBuildErrors: true, // Builds even with type errors
  },
  eslint: {
    ignoreDuringBuilds: true, // Skip ESLint errors
  },
};

Warning: ignoreBuildErrors: true silences errors without fixing them. Use it only temporarily while you fix the underlying type errors — never as a permanent solution.

Fix 2: Fix Module Resolution and Path Alias Errors

If @/components/... or other aliases resolve in dev but fail during build:

Ensure path aliases are in tsconfig.json:

// tsconfig.json
{
  "compilerOptions": {
    "baseUrl": ".",
    "paths": {
      "@/*": ["./src/*"],
      "@components/*": ["./src/components/*"],
      "@lib/*": ["./src/lib/*"]
    }
  }
}

Next.js reads tsconfig paths automatically — no extra next.config.js setup needed for TypeScript projects. But verify:

// next.config.js — only needed if NOT using TypeScript
const path = require('path');

module.exports = {
  webpack(config) {
    config.resolve.alias['@'] = path.resolve(__dirname, 'src');
    return config;
  },
};

Check for case sensitivity. Linux (production) is case-sensitive; macOS (development) is not. A file named Header.tsx imported as header.tsx works on Mac but fails in CI or on a Linux build server:

# Find case mismatches
git ls-files | grep -i header
# Verify the actual filename case
ls src/components/

Fix circular imports. Circular dependencies often only manifest at build time:

# Install madge to detect circular imports
npx madge --circular src/

Fix 3: Fix Environment Variable Issues in Build

NEXT_PUBLIC_* variables are inlined at build time — they must be present in the build environment, not just at runtime:

# Check which env vars are available during build
echo $NEXT_PUBLIC_API_URL  # Must be set in CI/build environment

# In CI (GitHub Actions):
- name: Build
  env:
    NEXT_PUBLIC_API_URL: ${{ secrets.NEXT_PUBLIC_API_URL }}
  run: npm run build

Validate required env vars at startup:

// src/lib/env.ts — validate at build time
const requiredEnvVars = [
  'NEXT_PUBLIC_API_URL',
  'DATABASE_URL',
  'NEXTAUTH_SECRET',
] as const;

for (const key of requiredEnvVars) {
  if (!process.env[key]) {
    throw new Error(`Missing required environment variable: ${key}`);
  }
}

export const env = {
  apiUrl: process.env.NEXT_PUBLIC_API_URL!,
  databaseUrl: process.env.DATABASE_URL!,
  nextAuthSecret: process.env.NEXTAUTH_SECRET!,
};

For Vercel deployments — add env vars in Project Settings → Environment Variables. Ensure they are set for the “Production” environment, not just “Preview.”

Fix 4: Fix Static Generation and getStaticProps Failures

If pages that use getStaticProps or generateStaticParams fail during build:

Error occurred prerendering page "/products/[id]"
FetchError: request to https://api.example.com/products failed

Add error handling in getStaticProps:

// app/products/[id]/page.tsx — App Router
export async function generateStaticParams() {
  try {
    const products = await fetchProducts();
    return products.map((p) => ({ id: p.id.toString() }));
  } catch (error) {
    console.error('Failed to fetch products for static generation:', error);
    return []; // Return empty array — page will use dynamic rendering
  }
}

// Or use dynamic rendering for pages that depend on runtime data
export const dynamic = 'force-dynamic'; // Skip static generation for this page

Pages Router — getStaticProps with error handling:

// pages/products/[id].tsx
export async function getStaticProps({ params }) {
  try {
    const product = await fetchProduct(params.id);
    return { props: { product }, revalidate: 60 };
  } catch {
    return { notFound: true }; // Returns 404 page instead of crashing build
  }
}

Set a build-time API base URL when your API is not available during CI builds:

// next.config.js
module.exports = {
  env: {
    API_BASE_URL: process.env.API_BASE_URL || 'https://api.example.com',
  },
};

Fix 5: Fix ESM / CommonJS Conflicts

Next.js uses a hybrid CJS/ESM environment. Some packages cause build crashes:

Error: require() of ES Module node_modules/some-package/index.js not supported.

Use next.config.js to transpile the problematic package:

// next.config.js
module.exports = {
  transpilePackages: [
    'some-esm-package',
    'another-esm-only-library',
  ],
};

For the digital envelope routines::unsupported error — Node.js 17+ changed the OpenSSL provider:

# Set the legacy OpenSSL provider (temporary fix)
export NODE_OPTIONS=--openssl-legacy-provider
npm run build

# Better fix — upgrade the package causing the issue, or upgrade Next.js
npm install next@latest

For require is not defined in client components:

// Wrong — using require() in a client component
'use client';
const fs = require('fs'); // fs is server-only

// Fix — move to a Server Component or API route
// Or use the server-only package to prevent accidental client use
import 'server-only';

Fix 6: Fix Build Memory Issues

Large Next.js apps sometimes run out of memory during build:

FATAL ERROR: CALL_AND_RETRY_LAST Allocation failed - JavaScript heap out of memory

Increase Node.js heap size:

# Set in package.json build script
{
  "scripts": {
    "build": "NODE_OPTIONS='--max-old-space-size=4096' next build"
  }
}

# Or export before running
export NODE_OPTIONS='--max-old-space-size=4096'
npm run build

Reduce build memory usage:

// next.config.js
module.exports = {
  // Disable source maps in production (saves memory and build time)
  productionBrowserSourceMaps: false,

  // Use SWC minifier (faster and uses less memory than Terser)
  swcMinify: true, // Default in Next.js 13+
};

Fix 7: Debug Build Failures Methodically

Run a verbose build to see the full error context:

next build 2>&1 | tee build.log
# Scroll to the first error — not the last

Test static generation locally:

next build && next start
# If this works locally but fails in CI, the issue is environment-specific

Check the .next directory for partial build artifacts:

rm -rf .next
next build
# Always do a clean build when diagnosing errors

Trace the exact file causing the error:

Next.js 12+ supports build traces:

NEXT_TELEMETRY_DISABLED=1 next build --debug

Common build error patterns and their causes:

Error messageLikely cause
Module not found: Can't resolvePath alias not configured, missing package
Type error:TypeScript type mismatch
Error occurred prerenderinggetStaticProps/generateStaticParams runtime error
heap out of memoryToo many pages or large dependencies
digital envelope routinesNode.js/OpenSSL version mismatch
require() of ES ModuleESM package used in CJS context

Still Not Working?

Test the build in a Docker container to replicate CI:

FROM node:20-alpine
WORKDIR /app
COPY package*.json ./
RUN npm ci
COPY . .
RUN npm run build
docker build -t nextjs-test .
# If the Docker build fails but local build works, the issue is environment-specific

Check for files imported at the module level that run at build time. Server-only code (database connections, file reads) at the top level of a module runs during next build when pre-rendering pages. Move such code inside functions:

// Bad — runs at import time during build
import { db } from '@/lib/db';
const config = db.query('SELECT * FROM config'); // Fails if DB not available at build

// Good — only runs when the function is called
export async function getConfig() {
  const { db } = await import('@/lib/db');
  return db.query('SELECT * FROM config');
}

For related Next.js issues, see Fix: Next.js Hydration Failed and Fix: Next.js Environment Variables Not Working.

F

FixDevs

Solo developer based in Japan. Every solution is cross-referenced with official documentation and tested before publishing.

Was this article helpful?

Related Articles