Loading chunk 77 failed due to timeout but Error reported on Sentry

Viewed 1812

I use Sentry (similar to Bugsnag) to monitor front end errors on my site.

On Sentry I have a lot of errors like this:

Error: Loading chunk 77 failed.
(timeout: https://www.exemple.com/77.6a28baf2f4e4ff5f87a6.js)

I do Lazy Loading but the old files are kept during a deployment, so the problem is not linked to a new version of the website deployed.

Like the error said, it seems to be a timeout, so it's probably the user connection that drops for a bit.

But what I don't understand is:

  • I can see these errors on Sentry: if the user connection drops while loading the website, how can he send something to Sentry that reports Bugs

  • On Sentry, the errors I'm looking at are from users using Windows, so it means they are on a desktop => Probability that their connection is dropping while on a desktop is low.

I searched the web for explanations for everything I found is about:

  • deployment and Lazy loading (I keep the old files, so it's not a problem)

  • Connection issue (Why do I see these errors reported)

Anyone has an idea of something to explore to try to find why theses errors occurs.

2 Answers

I had a similar issue (if not the same) some time ago which was seen in the cases where a user is active(in session) during and after a front-end deploy, which (from time to time) led to a situation where the user had references to some of the old files inside the angular app he/she was running (which were non-existent after the deploy), which caused those chunk errors.

The fix I used for this issue is a simple extension of the default SentryErrorHandler like so

@Injectable()
export class SentryErrorHandler implements ErrorHandler {
  constructor() { }
  handleError(error) {
    const chunkFailedMessage = /Loading chunk [\d]+ failed/;
    if (chunkFailedMessage.test(error.message)) {
      window.location.reload();
    } else {
      Sentry.captureException(error.originalError || error);
    }
  }
}

So with this solution, we are forcing the user to reload the application and get the latest artifacts (if something goes wrong). We also skip the error logging because it's not a message that brings us any value, because it's not something that we are able to fix, it's just how angular works.

Another way to fix this issue might be to preload all lazy modules when the app is idle, this way you won't be trying to load non-existent modules ever.

I have seen similar cases for which there is a timeout loading the chunk, but the timeout error is captured by the logs. This usually works as such because the library that handles the error logging could be using a web socket pipeline, and it has resiliency to recover from offline mode. The root cause of the timeout comes from the webpack library. There is a timeout limit for the chunk request. The concern here is that depending on what it needs, it can download several chunks that could be serialized on the server, so the timeout may be too little for connections with slow internet speed.

Things to look for:

  • Reduce the number of chunks
  • parallelism to handle the chunk requests (server, cdn)
  • Increase the timeout

This is a snippet on how the chunks get downloaded. Look at the network trace on the browser dev tools and look at the runtime-main####.js file to see what is downloading.

  var r, o = document.createElement("script");
                o.charset = "utf-8",
                o.timeout = 120,
                n.nc && o.setAttribute("nonce", n.nc),
                o.src = function(e) {
                    return n.p + "static/js/" + ({}[e] || e) + "." + {
                        0: "d59dddb1",
                        1: "88f2a1bf",
                        2: "abeb8f93",                       
                    }[e] + ".chunk.js"
                }(e);
                var b = new Error;
                r = function(c) {
                    o.onerror = o.onload = null,
                    clearTimeout(u);
                    var f = a[e];
                    if (0 !== f) {
                        if (f) {
                            var d = c && ("load" === c.type ? "missing" : c.type)
                              , t = c && c.target && c.target.src;
                            b.message = "Loading chunk " + e + " failed.\n(" + d + ": " + t + ")",
                            b.name = "ChunkLoadError",
                            b.type = d,
                            b.request = t,
                            f[1](b)
                        }
                        a[e] = void 0
                    }
                }
                ;
                var u = setTimeout((function() {
                    r({
                        type: "timeout",
                        target: o
                    })
                }
                ), 12e4);
                o.onerror = o.onload = r,
                document.head.appendChild(o)
Related