Skip to content

fix: turn AxiosError into a native error (#5394)#5558

Merged
jasonsaayman merged 10 commits intoaxios:v1.xfrom
brodo:is-native-error
Nov 11, 2025
Merged

fix: turn AxiosError into a native error (#5394)#5558
jasonsaayman merged 10 commits intoaxios:v1.xfrom
brodo:is-native-error

Conversation

@brodo
Copy link
Contributor

@brodo brodo commented Feb 18, 2023

Overview

This PR turns AxiosError into an instance of Error that returns true when checked with Node's utils.types.isNativeError.

Related Issue: #5394

Why this PR?

This PR is useful if axios is used in Node.js and the user wants to check if an instance of AxiosError, that moved across realms, is an Error. In practice this might happen if Node.js worker threads or vms are used.

A call to X instanceof Error compares X's prototype to the Error constructor in the current realm and thus returns false if the object was created in another realm. Node's isNativeError can be used to address this:

const assert = require('assert');
const vm = require('vm');
const {isNativeError} = require('util/types');

const context = vm.createContext({});
const differentRealmErr = vm.runInContext('new Error()', context);
assert(!(differentRealmErr instanceof Error)); // instanceof returns false
assert(isNativeError(differentRealmErr)); // isNativeError returns true

Node uses isNativeError(e) || e instanceof Error internally to check for errors.

What does the PR actually do?

Currently, the AxiosError constructor calls Error.call(this) but it does not return its result. With the change the result is returned. Here is a short illustration of the difference:

const assert = require('assert');
const {isNativeError} = require('util/types');

function MyErr() {
    return Error.call(this);
}
assert(isNativeError(new MyErr())); // instances of `MyErr` are native errors
assert(new MyErr() instanceof Error); // they are also instance of `Error`

function MyBrokenErr() {
    Error.call(this);
    this.__proto__ = Error.prototype;
}
assert(!isNativeError(new MyBrokenErr())); // instances of `MyBrokenErr` are _not_ native errors
assert(new MyBrokenErr() instanceof Error); // they are instance of `Error` however

Testing

I wrote a test which should only run in NodeJS environments. Sadly, I could not get the tests under test/specs running. The contributing guidelines mention grunt but I did not get it working. (Is this still up to date?) When running npm run test on a freshly checked-out repo I had several failures.

@brodo
Copy link
Contributor Author

brodo commented Feb 28, 2023

After getting even deeper into the Error rabbit hole I've simplified the code somewhat. The best and most readable way to do this would be to create a class that extends Error. I'll do that later today.

@brodo brodo marked this pull request as draft March 1, 2023 10:10
@brodo brodo marked this pull request as ready for review March 1, 2023 20:49
@brodo
Copy link
Contributor Author

brodo commented Mar 1, 2023

I think after the rewrite the code is much more understandable for people used to modern JavaScript.

@brodo brodo marked this pull request as draft March 1, 2023 22:08
@brodo brodo marked this pull request as ready for review March 1, 2023 22:12
@brodo
Copy link
Contributor Author

brodo commented Mar 1, 2023

I needed to update CanceledError to work with the new AxiosError. I also added a test for that.

@brodo brodo requested a review from hexiaokang March 1, 2023 22:27
@brodo
Copy link
Contributor Author

brodo commented Mar 14, 2023

@hexiaokang is there anything I can do to move forward with this?

@brodo
Copy link
Contributor Author

brodo commented Mar 29, 2023

By the way, the current version also calculates the stack trace twice, wich is a performance problem.

@jasonsaayman
Copy link
Member

@brodo any chance you can look at the conflicts please

@brodo
Copy link
Contributor Author

brodo commented Dec 9, 2024

@jasonsaayman I'll take a look later today.

@brodo brodo marked this pull request as draft December 9, 2024 13:22
@brodo brodo marked this pull request as ready for review December 9, 2024 13:44
@brodo
Copy link
Contributor Author

brodo commented Dec 9, 2024

@jasonsaayman should be done now

@jasonsaayman jasonsaayman added this to the v1.8.0 milestone Dec 9, 2024
@jasonsaayman jasonsaayman self-assigned this Dec 9, 2024
@jasonsaayman jasonsaayman requested review from jasonsaayman and removed request for hexiaokang December 9, 2024 14:12
@jasonsaayman jasonsaayman modified the milestones: v1.8.0, v2.0.0 Dec 14, 2024
@jasonsaayman jasonsaayman removed their assignment Dec 21, 2024
@jasonsaayman jasonsaayman requested a review from Copilot November 6, 2025 19:08
@jasonsaayman jasonsaayman added commit::fix The PR is related to a bugfix status::needs-rebase The PR requires a rebase and removed priority::low A low priority issue labels Nov 6, 2025
@jasonsaayman
Copy link
Member

@brodo could you rebase pls

Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull Request Overview

This PR refactors AxiosError and CanceledError from constructor functions using prototypal inheritance to ES6 classes with native extends syntax. The main changes modernize the codebase to use class syntax while maintaining the same API surface.

Key changes:

  • Converted AxiosError from a constructor function to an ES6 class that extends Error
  • Converted CanceledError to an ES6 class extending AxiosError
  • Added tests to verify both errors are recognized as native errors by Node.js

Reviewed Changes

Copilot reviewed 4 out of 4 changed files in this pull request and generated 5 comments.

File Description
lib/core/AxiosError.js Refactored from constructor function to ES6 class, moved static error code properties outside class definition with comment explaining parser limitation
lib/cancel/CanceledError.js Converted to ES6 class extending AxiosError, removed utils import as inherits helper is no longer needed
test/specs/core/AxiosError.spec.js Added tests for native error detection and static error code property usage
test/specs/cancel/CanceledError.spec.js Added test for native error detection

brodo added 9 commits November 8, 2025 11:28
Being an object returned by the 'Error' constructor turns something into a 'native error'.
This turns CanceledError into a native error.
If no error code is provided, use the code from the underlying error.
If a response is passed to the constructor, set the response status as a property.
@brodo
Copy link
Contributor Author

brodo commented Nov 8, 2025

@jasonsaayman done!

Copy link
Member

@jasonsaayman jasonsaayman left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM 🔥

@jasonsaayman jasonsaayman removed the status::needs-rebase The PR requires a rebase label Nov 11, 2025
@jasonsaayman jasonsaayman merged commit 1c6a86d into axios:v1.x Nov 11, 2025
11 checks passed
@github-project-automation github-project-automation bot moved this to Done in v2.0.0 Nov 11, 2025
Yashsingh045 added a commit to Yashsingh045/axios that referenced this pull request Nov 11, 2025
* fix: turn AxiosError into a native error (axios#5394)

Being an object returned by the 'Error' constructor turns something into a 'native error'.

* fix: simplify code in AxiosError

* fix: simplify code in AxiosError

* refactor: implement AxiosError as a class

* refactor: implement CanceledError as a class

This turns CanceledError into a native error.

* refactor: simplify AxiosError.toJSON

* fix: improve error code handling in `AxiosError.from`

If no error code is provided, use the code from the underlying error.

* fix: set error status in `AxiosError.constructor`

If a response is passed to the constructor, set the response status as a property.

* fix: remove unnecessary async

---------

Co-authored-by: Jay <jasonsaayman@gmail.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

commit::fix The PR is related to a bugfix

Projects

Status: Done

Development

Successfully merging this pull request may close these issues.

4 participants