Next.js build errors can be cryptic. This guide covers all common build failures and their solutions for Next.js 14 and 15.
Error: Module Not Found
Symptom:
Module not found: Can't resolve 'some-package'
Error: Cannot find module '@/components/MyComponent'
Solution 1 - Install missing package:
npm install some-packageSolution 2 - Fix path alias:
// tsconfig.json
{
"compilerOptions": {
"baseUrl": ".",
"paths": {
"@/*": ["./src/*"],
"@components/*": ["./src/components/*"]
}
}
}Solution 3 - Check case sensitivity:
// ❌ Wrong (Windows may work, Linux fails)
import MyComponent from '@/Components/MyComponent';
// ✅ Correct (match actual file path)
import MyComponent from '@/components/MyComponent';Error: Hydration Mismatch
Symptom:
Error: Hydration failed because the initial UI does not match what was rendered on the server
Warning: Expected server HTML to contain a matching <div> in <div>
Text content does not match server-rendered HTML
Cause 1 - Browser-only code in initial render:
// ❌ Causes hydration mismatch
export default function Component() {
return <div>{window.innerWidth}</div>; // window undefined on server
}
// ✅ Use useEffect for browser-only code
export default function Component() {
const [width, setWidth] = useState(0);
useEffect(() => {
setWidth(window.innerWidth);
}, []);
return <div>{width || 'Loading...'}</div>;
}Cause 2 - Date/time differences:
// ❌ Different on server vs client
<span>{new Date().toLocaleString()}</span>
// ✅ Suppress hydration warning or use useEffect
<span suppressHydrationWarning>{new Date().toLocaleString()}</span>
// ✅ Better: format on client only
const [time, setTime] = useState<string>();
useEffect(() => {
setTime(new Date().toLocaleString());
}, []);Cause 3 - Extension/browser modifications:
// Add suppressHydrationWarning to body for browser extensions
<body suppressHydrationWarning>
{children}
</body>Error: Dynamic Server Usage in Static Route
Symptom:
Error: Dynamic server usage: headers
Route /api/route couldn't be rendered statically because it used `headers`
Page "/page" is using dynamic server features
Solution 1 - Force dynamic rendering:
// app/page.tsx
export const dynamic = 'force-dynamic';
// or
export const revalidate = 0;Solution 2 - Move dynamic code to client:
// ❌ Using headers in page component
import { headers } from 'next/headers';
export default function Page() {
const headersList = headers();
// ...
}
// ✅ Use in route handler or move to client
// app/api/route.ts
import { headers } from 'next/headers';
export async function GET() {
const headersList = headers();
// ...
}Solution 3 - Use generateStaticParams:
// For dynamic routes that should be static
export async function generateStaticParams() {
const posts = await getPosts();
return posts.map((post) => ({
slug: post.slug,
}));
}Error: Image Optimization Failed
Symptom:
Error: Invalid src prop on `next/image`
Error: Image Optimization using default loader is not compatible with `next export`
Error: upstream image response failed
Solution 1 - Configure remote images:
// next.config.js
module.exports = {
images: {
remotePatterns: [
{
protocol: 'https',
hostname: 'example.com',
pathname: '/images/**',
},
{
protocol: 'https',
hostname: '**.cloudinary.com',
},
],
},
};Solution 2 - For static export:
// next.config.js
module.exports = {
output: 'export',
images: {
unoptimized: true, // Required for static export
},
};Solution 3 - Fix src path:
// ❌ Wrong - missing leading slash
<Image src="image.png" alt="..." width={100} height={100} />
// ✅ Correct - absolute path from public folder
<Image src="/image.png" alt="..." width={100} height={100} />
// ✅ Imported image (with dimensions)
import myImage from './image.png';
<Image src={myImage} alt="..." />Error: TypeScript Build Errors
Symptom:
Type error: Property 'x' does not exist on type 'y'
Type error: Argument of type 'string' is not assignable to parameter of type 'number'
Solution 1 - Fix PageProps typing (Next.js 15):
// ❌ Old pattern (Next.js 14)
export default function Page({ params }: { params: { id: string } }) {}
// ✅ New pattern (Next.js 15) - params is a Promise
export default async function Page({
params,
}: {
params: Promise<{ id: string }>;
}) {
const { id } = await params;
// ...
}Solution 2 - Fix searchParams typing:
// Next.js 15 - searchParams is also a Promise
export default async function Page({
searchParams,
}: {
searchParams: Promise<{ query?: string }>;
}) {
const { query } = await searchParams;
// ...
}Solution 3 - Ignore specific errors (temporary):
// @ts-ignore - TODO: Fix this type
const something = riskyOperation();
// @ts-expect-error - Expected to fail
const intentionalError = wrongType;Error: "use client" Directive Issues
Symptom:
Error: useState only works in Client Components
Error: You're importing a component that needs useEffect
Attempted to call useRouter() from the Server
Solution 1 - Add "use client" directive:
// Must be at the very top of the file
'use client';
import { useState } from 'react';
export default function ClientComponent() {
const [state, setState] = useState(false);
// ...
}Solution 2 - Split server/client components:
// ServerComponent.tsx (no directive needed)
import ClientPart from './ClientPart';
export default async function ServerComponent() {
const data = await fetchData(); // Server-side fetch
return <ClientPart initialData={data} />;
}
// ClientPart.tsx
'use client';
export default function ClientPart({ initialData }) {
const [data, setData] = useState(initialData);
// ...
}Error: ESLint/Build Strict Mode
Symptom:
Build failed due to ESLint errors
Error: `next/image` should be imported from `next/image` not `next/legacy/image`
Solution 1 - Fix ESLint issues:
# Auto-fix what's possible
npm run lint -- --fix
# Or run ESLint directly
npx eslint --fix .Solution 2 - Configure ESLint exceptions:
// .eslintrc.js
module.exports = {
rules: {
'@next/next/no-img-element': 'warn', // Downgrade to warning
'react-hooks/exhaustive-deps': 'warn',
},
};Solution 3 - Skip ESLint during build (not recommended):
// next.config.js
module.exports = {
eslint: {
ignoreDuringBuilds: true, // Use only if necessary
},
};Error: Memory Issues During Build
Symptom:
FATAL ERROR: Ineffective mark-compacts near heap limit Allocation failed
JavaScript heap out of memory
Solution 1 - Increase Node memory:
# Temporarily
NODE_OPTIONS="--max-old-space-size=8192" npm run build
# In package.json
{
"scripts": {
"build": "NODE_OPTIONS='--max-old-space-size=8192' next build"
}
}Solution 2 - Analyze bundle:
# Install bundle analyzer
npm install @next/bundle-analyzer
# next.config.js
const withBundleAnalyzer = require('@next/bundle-analyzer')({
enabled: process.env.ANALYZE === 'true',
});
module.exports = withBundleAnalyzer({
// your config
});
# Run analysis
ANALYZE=true npm run buildSolution 3 - Reduce bundle size:
// Dynamic imports for large components
import dynamic from 'next/dynamic';
const HeavyComponent = dynamic(() => import('./HeavyComponent'), {
loading: () => <p>Loading...</p>,
ssr: false, // Don't include in server bundle
});Error: API Route Issues
Symptom:
Error: API resolved without sending a response
TypeError: res.status is not a function
Solution - Use correct App Router patterns:
// app/api/route.ts (App Router)
import { NextResponse } from 'next/server';
export async function GET(request: Request) {
return NextResponse.json({ message: 'Hello' });
}
export async function POST(request: Request) {
const body = await request.json();
return NextResponse.json({ received: body }, { status: 201 });
}Quick Debug Commands
# Clear Next.js cache
rm -rf .next
# Clean install
rm -rf node_modules .next
npm install
# Build with verbose output
npm run build -- --debug
# Check for unused dependencies
npx depcheck
# Type check only
npx tsc --noEmitQuick Reference: Common Fixes
| Error | Quick Fix |
|-------|-----------|
| Module not found | npm install package or fix import path |
| Hydration mismatch | Use useEffect for browser-only code |
| Dynamic server usage | Add export const dynamic = 'force-dynamic' |
| Image optimization | Configure remotePatterns in config |
| TypeScript params | Use Promise<{ param }> pattern |
| "use client" needed | Add directive at top of file |
| Memory issue | NODE_OPTIONS="--max-old-space-size=8192" |
Complex Next.js Applications?
Building production Next.js applications requires performance optimization expertise. Our team offers:
- Performance audit and optimization
- Migration to App Router
- SSR/ISR strategy consulting
- Deployment pipeline setup