Webpack code splitting: ChunkLoadError - Loading chunk X failed, but the chunk exists
Asked Answered
D

4

34

I've integrated Sentry with my website a few days ago and I noticed that sometimes users receive this error in their console:

ChunkLoadError: Loading chunk <CHUNK_NAME> failed.
(error: <WEBSITE_PATH>/<CHUNK_NAME>-<CHUNK_HASH>.js)

So I investigated the issue around the web and discovered some similar cases, but related to missing chunks caused by release updates during a session or caching issues.

The main difference between these cases and mine is that the failed chunks are actually reachable from the browser, so the loading error does not depend on the after-release refresh of the chunk hashes but (I guess), from some network related issue. This assumption is reinforced by this stat: around 90% of the devices involved are mobile.

Finally, I come to the question: Should I manage the issue in some way (e. g. retrying the chunk loading if failed) or it's better to simply ignore it and let the user refresh manually?


2021.09.28 edit:

A month later, the issue is still occurring but I have not received any report from users, also I'm constantly recording user sessions with Hotjar but nothing relevant has been noticed so far.

I recently had a chat with Sentry support that helped me excluding the network related hypotesis:

Our React SDK does not have offline cache by default, when an error is captured it will be sent at that point. If the app is not able to connect to Sentry to send the event, it will be discarded and the SDK will no try to send it again.

Rodolfo from Sentry

I can confirm that the issue is quite unusual, I share with you another interesting stat: the user affected since the first occurrence are 882 out of 332.227 unique visitors (~0,26%), but I noticed that the 90% of the occurrences are from iOS (not generic mobile devices as I noticed a month ago), so if I calculate the same proportion with iOS users (794 (90% of 882) out of 128.444) we are near to a 0,62%. Still small but definitely more relevant on iOS.

Densify answered 3/9, 2021 at 15:33 Comment(9)
We're also facing the same issue. These are not old chunks that don't exist anymore, the chunks are definitely still available and can be loaded. Apparently for some users the chunk isn't available at some point. Network issues could be a cause, but that seems like it should be fairly rare (how often do people load a page, then lose internet connection?) Would love to hear why this is happening and if there are any good solutions.Paderna
@Paderna - Does this chunk has anything particular like being large? Do you have a complete stack trace of the error?Sternpost
@Newbie, no, in fact most of the chunks are quite small. One I just checked was under 1kb. I do have a stack trace. The first line is some code in webpack: webpack:///webpack/bootstrap, then [native code], then our app's definition of a lazyImport function, which is defined as: return import( /* webpackChunkName: "[request]" */ "../" + moduleName ).Paderna
Could you possibly replicate the problem? For now, I could only make a supposition. The lazy chunk, when ready, it should invoke a function that was defined in the file that requested it. If that function is invoked, the chunk status is changed from loading to done. However, if that fn is not called, that error will be thrown. For instance, if you have a dynamic import() in a main.js file, the outputted file corresp. to main.js will have the logic responsible for throwing that error.Misquote
Thanks everyone for the interest in this post, I'm glad i'm not alone! I tried to replicate the issue but with no success. Anyway @AndreiGătej, your supposition is interesting. I'm updating the issue with new details I collected in the past days.Densify
The main difference between these cases and mine is that the failed chunks are actually reachable from the browser. How do you know this?Chlorite
Thank you @Chlorite for your attention! I know that because I tried to access some of those chunks (the filename was in the error trace) and they all returned the right content. Furthermore, if the issue was linked to the changing hashes I should've seen some spikes near to the releases, instead the error frequency it's constant over time.Densify
Is there any update on this? I'm having this problem as well. Service workers are not turned on, we don't have a CDN, and the chunks are relatively small and are not outdated.. Its also not a matter of an outdated user session as well, we get these 2 or 3 weeks after the last deployment.Eladiaelaeoptene
I have been trying to find the reason for getting ChunkLoadError's for a while and these failures are for chunks which do exist. It's also curious that these errors are being reported to our defect tracker, implying it is not a network issue... I believe I have stumbled on a potential cause whilst debugging another issue. If I navigate quickly across pages, the chunks' network request gets cancelled and this returns a ChunkLoadError... It would be good to somehow detect when a chunk failed due to this reason and ignore the error.Flux
T
9

The chunk is reachable doesn't mean the user's browser can parse it. For example, if the user's browser is old. But the chunk contains new syntax.

Webpack loads the chunk by jsonp. It insert <script> tag into <head>. If the js chunk file is downloaded but cannot parsed. A ChunkLoadError will be throw.

You can reproduce it by following these steps. Write an optional chain and don't compile it. Ensure it output to a chunk.

const obj = {};
obj.sub ??= {};

Open your app by chrome 79 or safari 13.0. The full error message looks like this:

SyntaxError: Unexpected token '?'           // 13.js:2
MAX RELOADS REACHED                         // chunk-load-handler.js:24
ChunkLoadError: Loading chunk 13 failed.    // trackConsoleError.js:25
(missing: http://example.com/13.js)
Totten answered 20/5, 2022 at 17:49 Comment(1)
This is a most excellent answer! I can't believe Loading chunk ... failed. (missing: https://... actually doesn't mean missing at all - it means that Webpack regards it as missing, but this could be caused by an actual JavaScript error when a successful network request is interpreted by the browser. In our case, we had dropped old versions of Chrome from our browserslistrc, and loading the pack in the old browser was causing a Uncaught SyntaxError: Unexpected token '.'.Bette
C
5

This is most likely happening because the browser is caching your app's main HTML file, like index.html which serves the webpack bundles and manifest.

First I would ensure your web server is sending the correct HTTP response headers to not cache the app's index.html file (let's assume it is called that). If you are using NGINX, you can set the appropriate headers like this:

location ~* ^.+.html$ {
  add_header Cache-Control "no-store max-age=0";
}

This file should be relatively small in size for a SPA, so it is ok to not cache this as long as you are caching all of the other assets the app needs like the JS and CSS, etc. You should be using content hashes on your JS bundles to support cache busting on those. With this in place visits to your site should always include the latest version of index.html with the latest assets including the latest webpack manifest which records the chunk names.

If you want to handle the Chunk Load Errors you could set up something like this:

import { ErrorBoundary } from '@sentry/react'

const App = (children) => {
  <ErrorBoundary
    fallback={({ error, resetError }) => {
      if (/ChunkLoadError/.test(error.name)) {
        // If this happens during a release you can show a new version alert
        return <NewVersionAlert />

        // If you are certain the chunk is on your web server or CDN
        // You can try reloading the page, but be careful of recursion
        // In case the chunk really is not available
        if (!localStorage.getItem('chunkErrorPageReloaded')) {
          localStorage.setItem('chunkErrorPageReloaded', true)
          window.location.reload()
        }
      }

      return <ExceptionRedirect resetError={resetError} />
  }}>
    {children}
  </ErrorBoundary>
}

If you do decide to reload the page I would present a message to the user beforehand.

Chlorite answered 3/10, 2021 at 15:0 Comment(4)
I don't think this is correct. If the browser was caching the index.html and manifest, then the chunks it would be pointing to would be either outdated or existing (depending on if that chunk needed to be updated). As the OP said, he's seeing this for chunks that are NOT outdated... but even if they were outdated, for the chunk load error to occur, the chunk should not be available at the given URL - but they are. That's the point - why are we seeing ChunkLoadErrors for a URL that is returning the right chunk?Paderna
Whether the chunk still exists for a cached manifest depends on how you manage your assets. Do you overwrite your assets for each deployment or do you keep the old ones around for some time? Maybe you're using a CDN and the assets are not available in particular regions? All that was stated was that the OP was able to access the chunks that were in error, but not exactly how he was able to access them or from where.Chlorite
The OP mentioned in his question: The main difference between these cases and mine is that the failed chunks are actually reachable from the browser . And the title of the question includes "but the chunk exists". The CDN theory could make sense, though.Paderna
Unfortunately this is not my case, there is no CDN. But yeah, reachable from the browser is a bit misleading!Densify
F
1

I also had such chunk load issue. I have angular app that is hosted by aspnet 6.0 in IIS. index.html has cache-control max-age=0, chunk files have hash in name e.g. main.4591141fc2c0d492.js and cache-control set to max-age=2592000. Problem with chunk loading began when I added public (https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Cache-Control#public) directive for chunk files. Problem was volatile. Usually it worked ok but time to time server returned empty files. Empty file is a bad chunk so caused ChunkLoadError. The problem got worse since these files were cached. Reloading the page did not fix the problem since broken (empty) files were cached. Users had to clean browser cache to fix the issue.

Removing public cache directive resolved the issue.

Freestanding answered 21/10, 2023 at 1:57 Comment(0)
I
-1

I have cleaned the browser cache it worked fine for me . but still need to understand what was that )

Ila answered 20/2 at 15:31 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.