Skip to content

fetch adapter: handling of network errors different from xhr #6374

@glsignal

Description

@glsignal

Describe the bug

Hello! First up: thank you for the work to include a fetch adapter in axios, this is fantastic ❤️

I noticed a (potential) issue, or at least a difference in behaviour, when switching adapters around the production of ERR_NETWORK.

Glancing at the fetch adapters code, it looks like the issue comes from the if (err.name === 'NetworkError') { check, which works with XHR but fetch rejects with a TypeError with Failed to fetch as the message. It might just be a matter of swapping the strings, in which case that's straight forward.

What I wasn't sure about, is how wide that "Failed to fetch" scope is (MDN only describes the exception class), and whether it overlaps with any of the other error types that are listed. MDN documents a number of failure modes for this TypeError, which may complicate things.

Happy to help/open a PR when needed, though I'd like to iron out the uncertainty around the error modes first

To Reproduce

https://github.com/glsignal/scratch-axios-network-error or https://codesandbox.io/p/github/glsignal/scratch-axios-network-error/main

Code snippet

import { beforeAll, afterAll, describe, expect, it } from "vitest";

import { http, HttpResponse } from "msw";
import { setupServer } from "msw/node";

import axios, { AxiosError } from "axios";

const server = setupServer();

beforeAll(() => {
  server.listen();
});

afterAll(() => {
  server.close();
});

describe("error events", () => {
  async function buildNetworkError(adapter) {
    server.use(http.get("/test", () => HttpResponse.error()));

    try {
      return await axios.get("http://localhost/test", { adapter });
    } catch (event) {
      return event;
    }
  }

  describe("using xhr adapter", () => {
    it("indicates that it is a network error", async () => {
      const error = await buildNetworkError("xhr");

      expect(error.code).toEqual(AxiosError.ERR_NETWORK);
    });
  });

  describe("using fetch adapter", () => {
    it("indicates that it is a network error", async () => {
      const error = await buildNetworkError("fetch");

      expect(error.code).toEqual(AxiosError.ERR_NETWORK);
    });
  });
});

Expected behavior

I'd expect error.code to equal AxiosError.ERR_NETWORK with both adapters.

Axios Version

1.7.0-beta.0

Adapter Version

fetch

Browser

No response

Browser Version

No response

Node.js Version

No response

OS

No response

Additional Library Versions

No response

Additional context/Screenshots

No response

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions