What this usually means
React's lazy loading via import() splits your bundle into multiple JS chunks loaded on demand. 'Loading chunk failed' usually surfaces when the client tries to fetch a chunk file that no longer exists at the requested URL—typically due to a deployment that invalidates or replaces chunk files without clients reloading the main bundle. This often happens in SPAs that remain open during a deployment, causing the app to reference obsolete build artifacts.
The first ten minutes — establish facts before touching code.
- 1Open Chrome DevTools → Network tab, filter for .js, and reproduce navigation—look for 404/500 on chunk URLs.
- 2Check the error in Console: confirm if 'Loading chunk X failed' or similar appears.
- 3Validate the chunk URL failing to load: is it present on disk/in your static hosting location?
- 4Compare the failing chunk filename hash to your latest deployment; does it match or is it stale?
- 5Check if a hard refresh (Ctrl+Shift+R) resolves the error for affected users.
- 6Review deployment logs or S3/cloud storage versions for deleted or invalidated chunks.
The specific files, logs, configs, and dashboards that usually own this bug.
- searchBrowser Network and Console tabs (DevTools)
- searchwebpack-stats.json or stats.html for chunk mapping
- search./build/static/js/ or your CDN bucket for chunk presence
- searchYour reverse proxy/CDN cache invalidation settings (e.g., CloudFront behaviors)
- searchService worker code (src/serviceWorker.js or custom implementations)
- searchApp.js or wherever React.lazy() / Suspense are configured
- searchYour deployment pipeline scripts for asset deletion logic
Practical causes, not theory. These are the things you will actually find.
- warningUser has an older HTML/entry bundle referencing outdated chunk filenames
- warningCDN or reverse proxy caching old HTML but new chunks
- warningAggressive asset pruning in deployment removes previous build chunks too early
- warningService worker serving stale cached chunk files or HTML
- warningChunk hash mismatch between deployed HTML and static assets
- warningIncorrect publicPath or asset URL config in webpack or CRA
Concrete fix directions. Pick the one that matches your root cause.
- buildConfigure your deployment to retain old chunk files for at least 48h after a new deploy
- buildSet up cache-busting headers and proper cache invalidation on your CDN or server
- buildInvalidate HTML and JS assets atomically—never deploy new JS without updating main index.html
- buildIf using service workers, update them to clean up outdated caches and force clients to reload on new deploy
- buildImplement an error boundary that triggers window.location.reload() on chunk load failure
- buildEnsure webpack's publicPath accurately points to your current static files location
A fix you cannot prove is a guess. Close the loop.
- verifiedTest client-side navigation after deployment from multiple browsers and incognito tabs
- verifiedSimulate a slow client with old HTML (open before deploy) and verify navigation reloads or errors are handled
- verifiedMonitor error reporting (Sentry, Datadog) for recurrence of 'Loading chunk failed' post-fix
- verifiedConfirm that old and new chunks coexist in your CDN/static storage for the desired overlap period
- verifiedTest service worker updates and cache invalidation with Lighthouse or Workbox tools
Things that make this bug worse or harder to find.
- warningDeleting previous build chunks immediately on deployment
- warningRelying solely on cache headers without testing multi-version asset loading
- warningIgnoring service worker cache when troubleshooting—stale caches are a top cause
- warningAssuming a hard refresh fixes it for all users (most users won’t do this)
- warningUsing inconsistent or dynamic publicPath values between builds
- warningFailing to atomically update both HTML and JS assets
'Loading chunk 13 failed' in Production after Blue/Green Deploy
Timeline
- 09:00Blue/green deploy starts; old chunk files purged from S3.
- 09:05New build activates; index.html now references new chunk hashes.
- 09:20Sentry spikes: 'Loading chunk 13 failed' errors from US/EU users.
- 09:28Support reports blank UI after navigating to /dashboard.
- 09:32Engineer traces 404s for /static/js/13.abcd1234.chunk.js in Chrome DevTools.
- 09:40Confirm users with browser tab open before deploy hit the bug, new sessions work fine.
- 10:00Hotfix: redeploys old chunks and configures S3 bucket to retain previous build for 48h.
We did a blue/green deployment with React lazy-loaded routes. The ops script deleted the previous build's chunks from S3 as soon as the new version was activated, to save storage costs.
About 15 minutes later, Sentry was blowing up with 'Loading chunk 13 failed' errors, and support pinged us about users getting blank screens. All on routes using React.lazy. Anyone who navigated from an already-open tab was broken.
We realized the main bundle in their browser referenced old chunk hashes, but those files were gone from S3. A quick fix: restore the old chunks, adjust deployment to retain N-1 versions, and force the service worker to update.
Root cause
Premature deletion of old chunk files caused clients with cached HTML to request JS assets that no longer existed, breaking lazy-loaded routes.
The fix
Deployment script now retains previous two builds’ chunks for 48 hours, and service worker explicitly reloads after deploy.
The lesson
Never delete previous chunk files immediately; always ensure clients with old HTML can fetch their referenced chunks.
React.lazy uses dynamic import(), which prompts webpack to carve out separate JS files (chunks) loaded only when needed (e.g., upon route navigation). These chunk URLs are embedded in the compiled main bundle, generated at build time.
If the main bundle is cached or not refreshed on client devices, and you deploy a new build with different chunk hashes (due to code changes or even unrelated dependency upgrades), the browser tries to fetch chunks by their old names. If those files are gone from your server or CDN, the fetch fails and React throws 'Loading chunk failed.'
Most chunk load errors are caused by a mismatch in state between client cache and your asset hosting. S3, CloudFront, or nginx doesn't know to keep old chunks around—unless you tell it to. It’s not enough to cache-bust only the index.html; users need the JS chunks their HTML references too.
Aggressive CI/CD pipelines often delete previous builds immediately, breaking active sessions. Similarly, service workers may keep serving old HTML and JS, masking the problem in local dev but causing breakage for real users.
You can catch chunk load errors by wrapping lazy components or routers with an error boundary. In the error boundary, detect chunk load failures (the error message will usually include 'Loading chunk'), and trigger a full window.location.reload(). This gives the user a chance to get fresh HTML and valid chunk references.
Example: componentDidCatch(error) { if (error?.message?.match(/Loading chunk/)) { window.location.reload(); } }
Never delete old chunks immediately; retain at least one prior build’s assets for 24–48h, or longer if your sessions last.
Ensure CDN cache invalidation is atomic: both HTML and JS get refreshed together.
If using service workers, update them to detect version changes and force a refresh.
Monitor real-user metrics and Sentry for chunk loading failures after every deploy; spikes almost always indicate a cache or asset retention issue.
Frequently asked questions
Why does this only happen after deployment?
Because users with open sessions have cached main bundles referencing old chunk filenames. If you deploy and delete those chunks, they get 404s when navigating.
Can't cache headers solve this?
Cache headers help only if you never purge old chunks too soon. Most hosting/CDN setups need explicit asset retention logic—don’t count on headers alone.
What about prefetching all chunks?
Prefetching helps with perceived speed but doesn’t prevent this error. If the chunk file referenced in the old HTML is gone, prefetching fails the same way.
Does this affect Create React App or just custom setups?
Both are affected. CRA uses webpack’s chunking and lazy loading under the hood; root causes are the same.
How do I debug this on a live site?
Open DevTools → Network tab, reproduce the error, and look for 404/500s on chunk .js requests. Check which chunk hashes are missing from your static hosting.