ChunkLoadError After Deploy in Next.js: Fix Guide 2026
Users get 'Loading chunk failed' right after you deploy? Version skew is the cause. Here is how to stop it with skew protection, caching rules, and a one-time reload.
ChunkLoadError ("Loading chunk 123 failed") after a deploy is caused by version skew: a user's open tab still runs the old JavaScript, which requests chunk files that no longer exist on the new deployment. Fix it with deployment pinning, correct cache headers, and a one-time automatic reload.
You will usually see one of these in the browser console:
ChunkLoadError: Loading chunk 482 failed.
Failed to fetch dynamically imported module: https://app.example.com/_next/static/chunks/...
It hits users who had the site open during your deploy, and it shows up as "random" broken navigation, buttons that do nothing, or a blank page after a click.
Why It Happens
- User loads the page on deploy A. The HTML references
main-abc123.js. - You ship deploy B. File names change because their content hashes changed.
- The user clicks a link. Next.js lazy-loads a route chunk named by deploy A.
- The server (now deploy B) returns 404 for that file, or returns your HTML 404 page, and the import fails.
This is a close cousin of the problems in Next.js deployment failures on Vercel, except the deploy itself succeeded.
Fix 1: Turn On Skew Protection (Vercel)
Vercel offers Skew Protection, which pins each client to the deployment it loaded and routes its asset and API requests to that same deployment. Enable it in the project settings. It removes most chunk errors with no code change. Check the Vercel docs for plan availability and the retention window.
Fix 2: Do Not Cache the HTML Shell Forever
If a CDN or service worker serves stale HTML that points to deleted chunks, users hit the error even on a fresh visit.
// next.config.ts
const nextConfig = {
async headers() {
return [
{
source: '/:path*',
headers: [{ key: 'Cache-Control', value: 'public, max-age=0, must-revalidate' }],
},
]
},
}
export default nextConfig
Hashed files under /_next/static/ are safe to cache forever. Only the HTML needs revalidation. If you run a PWA or service worker, make sure it does not precache old HTML.
Fix 3: Reload Once When It Still Happens
Even with protection, long-lived tabs and self-hosted setups will occasionally fail. Catch it and reload a single time:
// app/global-error.tsx
'use client'
import { useEffect } from 'react'
export default function GlobalError({ error }: { error: Error }) {
useEffect(() => {
const isChunk = /ChunkLoadError|Loading chunk|dynamically imported module/i.test(
error.name + error.message
)
if (isChunk && !sessionStorage.getItem('chunk-reloaded')) {
sessionStorage.setItem('chunk-reloaded', '1')
window.location.reload()
}
}, [error])
return <html><body><p>Something went wrong. Please refresh.</p></body></html>
}
The sessionStorage flag prevents a reload loop, which would be an even worse bug (see Next.js redirect loops for a related failure).
Fix 4: Keep Old Assets Available (Self-Hosted)
On your own servers, deleting the previous .next/static on every deploy guarantees skew. Keep the last one or two builds of static assets, or serve them from object storage with a long retention.
Measure It
| Signal | Healthy | Problem |
|---|---|---|
| ChunkLoadError count after deploy | Near zero | Spike for 10-30 minutes |
404s on /_next/static/* |
Rare | Bursts right after release |
| Sessions with a reload | Low | Rising after every release |
If you only look at server logs you will miss it, because the failure happens in the browser. Read Next.js error monitoring in production to capture client errors alongside server ones.
Let Relia Watch Each Release
Relia watches client errors in users' sessions and learns what is normal for your app. A ChunkLoadError spike after a release shows up as an incident with the likely cause and one next step. On request it writes a fix plan for the cache-header or error-boundary change with a "Copy for your AI assistant" button; Relia doesn't change code itself, and after you ship it checks the fix against live traffic.
FAQ
What does "Loading chunk failed" mean in Next.js?
The browser tried to download a JavaScript file that no longer exists on the server, usually because a new deployment replaced it.
Will users have to refresh manually?
Not with the one-time reload above. Without it, a manual refresh fixes it, which is why the bug is easy to dismiss and hard to reproduce.
Can I prevent it entirely?
Skew protection or keeping old assets removes nearly all cases. Keep the reload fallback for the rest.