Have 30-200 Employees? Make $50k-$500k selling your data for AI Training.

Learn More
Next.js Chunk Load Error: How to Fix Production Failures
SitePoint Premium
Stay Relevant and Grow Your Career in Tech
  • Premium Results
  • Publish articles on SitePoint
  • Daily curated jobs
  • Learning Paths
  • Discounts to dev tools
Start Free Trial

7 Day Free Trial. Cancel Anytime.

The ChunkLoadError, often surfaced in browser consoles as "Loading chunk [hash] failed" (webpack) or "Failed to load chunk /_next/static/chunks/..." (Turbopack), is a common production failure in Next.js applications using the App Router. This guide is a diagnosis-first playbook rather than a single silver-bullet fix, covering at least five distinct root causes and providing a structured diagnostic decision tree for every occurrence.

Table of Contents

Prerequisites

This guide covers the App Router in Next.js 14 through 16 (the current release is 16.3.8 as of October 4, 2026) and uses the Node.js version your Next.js release requires (Next.js 16 needs Node.js 20.9 or later). Fix 5 examples use Workbox 7.x. Verify your versions before applying any changes:

next --version
node --version

Why Chunk Load Errors Haunt Production

The ChunkLoadError, often surfaced in browser consoles as "Loading chunk [hash] failed" (webpack) or "Failed to load chunk /_next/static/chunks/..." (Turbopack), is a common production failure in Next.js applications using the App Router. It fires when the browser tries to fetch a code-split JavaScript chunk via a dynamic import() call and receives either a non-200 response or content that cannot be parsed as JavaScript.

The result: broken client-side navigation and blank screens. Users stop trusting client-side navigation entirely.

This error does not reproduce locally. Local development runs a single deployment in a single environment with no CDN layer, no reverse proxy, and no stale cached HTML documents referencing outdated chunk hashes.

This error does not reproduce locally. Local development runs a single deployment in a single environment with no CDN layer, no reverse proxy, and no stale cached HTML documents referencing outdated chunk hashes. The conditions that trigger the failure in production simply do not exist on localhost:3000.

This guide is a diagnosis-first playbook rather than a single silver-bullet fix. The error has at least five distinct root causes, and applying the wrong fix wastes time while users continue to hit broken pages. The diagnostic decision tree below provides a structured starting point for every occurrence.

How Next.js Code-Splitting Works (and Where It Breaks)

Hash-Based Chunk URLs

Next.js automatically code-splits application bundles into discrete files stored under _next/static/chunks/. Next.js gives each file a content-hashed filename, meaning the hash changes whenever the file's contents change. During client-side navigation, the App Router triggers dynamic import() calls to fetch only the chunks required for the target route. This reduces initial transfer size by deferring non-critical code, but it introduces a dependency: the chunk URL embedded in the currently loaded JavaScript must resolve to a valid JavaScript file on the server or CDN.

The Three Failure Points

Every ChunkLoadError traces back to one of three locations in the request lifecycle:

  1. Origin or CDN. The chunk file is absent from the server, typically because a new deployment replaced the _next/static/ directory and the old hashed files no longer exist. Alternatively, the CDN returns the wrong content (such as an HTML error page) for the chunk URL.
  2. Network path. A proxy, middleware layer, or Web Application Firewall intercepts the chunk request and returns something other than the expected JavaScript. This includes authentication middleware that redirects unauthenticated requests to a login page and corporate proxies that inject block pages.
  3. Client cache. The browser holds a stale HTML document that references chunk hashes from a previous deployment. When the user navigates, the import() call requests a hash that no longer exists on the current origin.

Diagnostic Decision Tree

The following numbered flowchart provides a systematic path from symptom to root cause. Each terminal branch references the corresponding fix section below.

  1. Can the failing chunk URL be captured? Open the browser console, locate the full URL in the ChunkLoadError message (e.g., https://example.com/_next/static/chunks/app/dashboard-a1b2c3d4.js), and copy it.
  2. Inspect the failing URL with curl. Run curl -sI to inspect response headers (status code, content-type, cache-control), then run curl -s | head -c 80 to confirm the response body begins with JavaScript, not HTML (e.g., the first bytes should not be or {"error").
    • Non-200 status, wrong content-type, or HTML body → proceed to the CDN / Origin branch (step 3).
    • 200, correct content-type, and JavaScript body → proceed to the Client / Proxy branch (step 4).
  3. CDN / Origin branch:
    • Is there deploy skew? Check whether the chunk hash in the URL matches the currently deployed build. → See Fix 1: Eliminate Deploy Skew with deploymentId.
    • Has the CDN cache been purged after deploy? Check for stale cached 404s or stale HTML error pages. → See Fix 3: CDN Caching and Cache-Header Hygiene.
    • Are _next/static/ assets served with immutable cache headers? → See Fix 3.
  4. Client / Proxy branch:
    • Does middleware intercept _next/static/* paths? Test by curling with and without auth cookies. → See Fix 2: Audit Your Middleware Matcher.
    • Is a service worker serving stale chunks from a precache? Check the Application panel in DevTools. → See Fix 5: Service Workers and Offline Caching Conflicts.
    • Is an ad-blocker or corporate proxy rewriting the response? Test from a clean browser profile.

The following curl commands provide the header and body checks referenced above. Replace the placeholder URLs with your actual chunk URLs:

# Check status code, content-type, and cache headers
curl -sI https://example.com/_next/static/chunks/app/dashboard-a1b2c3d4.js

# Verify the response body starts with JavaScript, not HTML
curl -s https://example.com/_next/static/chunks/app/dashboard-a1b2c3d4.js | head -c 80

# Check deployment ID header if applicable
curl -s -D - -o /dev/null https://example.com/_next/static/chunks/app/dashboard-a1b2c3d4.js \
  | grep -iE "HTTP/|content-type|cache-control|x-nextjs-deployment-id"

# Compare response with and without auth cookies
# Replace session=abc123 with a valid session cookie from your browser's DevTools → Application → Cookies
curl -sI -b "session=abc123" https://example.com/_next/static/chunks/app/dashboard-a1b2c3d4.js
curl -sI https://example.com/_next/static/chunks/app/dashboard-a1b2c3d4.js

If the authenticated and unauthenticated responses differ in status code or content-type, middleware is the likely culprit.

Fix 1: Eliminate Deploy Skew with deploymentId

What Deploy Skew Is

Deploy skew occurs when users have open browser tabs holding an HTML document from a previous deployment. That HTML contains

SitePoint TeamSitePoint Team

Sharing our passion for building incredible internet things.

© 2000 – 2026 SitePoint Pty. Ltd.
This site is protected by reCAPTCHA and the Google Privacy Policy and Terms of Service apply.