Skip to content

JavaScript network error

A request or a script download failed before the browser got a response. The text depends on the API and the browser, but the causes are the same: the connection, a block, or a file that is gone.

Updated September 24, 2026 by the Squasher team

What the error means

Network errors reach your code in different ways. fetch() rejects with a TypeError. Axios rejects with an AxiosError that has code ERR_NETWORK. XMLHttpRequest fires an error event, and its status is 0.

A bundler that loads code on demand fails the same way when a chunk file cannot be downloaded. After a deploy, users on the old version ask for chunk files that no longer exist.

The error message in each browser or library
WhereMessage
fetch in Chrome, EdgeTypeError: Failed to fetch
fetch in FirefoxTypeError: NetworkError when attempting to fetch resource.
fetch in SafariTypeError: Load failed
AxiosAxiosError: Network Error
webpack lazy chunkChunkLoadError: Loading chunk 42 failed.
Vite dynamic import in ChromeTypeError: Failed to fetch dynamically imported module

Common causes

  • The device is offline, or it changed networks during the request, for example from Wi-Fi to cellular.
  • DNS, TLS, or the connection failed: the host is down, the name is wrong, or the certificate is not valid.
  • The browser blocked the request: CORS, mixed content, a Content Security Policy connect-src rule, or an extension.
  • A deploy removed old chunk files while users still ran the previous version of the app.
  • Your own timeout cancelled the request. That is an AbortError or TimeoutError, not a network error, and it needs its own handling.

Reproduce it

In DevTools, open Network and set throttling to Offline. Then run a request. Use Block request URL on a chunk file to see a chunk load error.

TypeScript
try {  await fetch("/api/orders");} catch (error) {  console.log(error); // TypeError: Failed to fetch} console.log(navigator.onLine); // false

Fix it

  1. Set a timeout, and handle it separately

    AbortSignal.timeout() cancels a slow request with a TimeoutError. Show a slow-server message for it, and an offline message for a real network error.

    TypeScript
    try {  const response = await fetch("/api/orders", {    signal: AbortSignal.timeout(8000),  });} catch (error) {  if (error instanceof DOMException && error.name === "TimeoutError") {    showMessage("The server is slow. Try again.");  } else {    showMessage("You appear to be offline.");  }}
  2. Wait for the connection before you retry

    Retry reads that are safe to repeat after the browser is back online. navigator.onLine can say true on a network that has no internet, so keep a retry limit.

    TypeScript
    async function whenOnline() {  if (navigator.onLine) return;  await new Promise((resolve) =>    window.addEventListener("online", resolve, { once: true }),  );}
  3. Reload once when a chunk is gone after a deploy

    When a lazy import fails, load the new version of the app one time. Store a flag so a real outage does not cause a reload loop.

    TypeScript
    async function loadSettings() {  try {    return await import("./settings-page");  } catch (error) {    if (!sessionStorage.getItem("reloaded-for-deploy")) {      sessionStorage.setItem("reloaded-for-deploy", "1");      window.location.reload();    }    throw error;  }}

Catch it in production

The Squasher browser SDK sends this error to your project when it happens, so you do not wait for a user to report it.

  • Uncaught rejections from fetch and dynamic imports are captured automatically, with the page URL, release, and session ID.
  • The release on each event shows when chunk errors start right after a deploy.
  • Session replay records failed network requests next to what the user saw.
src/api.ts
import { init, captureError } from "@squasher-ai/browser"; init({  apiKey: import.meta.env.VITE_SQUASHER_API_KEY,  projectId: import.meta.env.VITE_SQUASHER_PROJECT_ID,  release: import.meta.env.VITE_GIT_SHA,}); export async function getOrders() {  try {    return await fetch("/api/orders", { signal: AbortSignal.timeout(8000) });  } catch (error) {    captureError(error as Error, { endpoint: "/api/orders" });    throw error;  }}
app.squasher.ai/acme/shop-web/issues

TypeError: Failed to fetch dynamically imported module

UnhandledRejection(TypeError)

HighUnresolvedError
Events
640
First seen
38m ago
Last seen
now
Environment
production
Service
shop-web

Example code and issue.

JavaScript error monitoring with Squasher

Catch the next one first.

Send browser errors to Squasher and fix them before the support ticket arrives.

Free plan. No credit card required.