Visitar URL original
fix: turn AxiosError into a native error (#5394) by brodo · Pull Request #5558 · axios/axios · GitHub
Skip to content

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

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

jasonsaayman merged 10 commits into
axios:v1.xfrom
brodo:is-native-error

Conversation

@brodo

@brodo brodo commented Feb 18, 2023 •

Copy link
Copy Markdown
Contributor

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

brodo commented Feb 28, 2023 •

Copy link
Copy Markdown
Contributor Author

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

brodo commented Mar 1, 2023

Copy link
Copy Markdown
Contributor Author

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

brodo commented Mar 1, 2023

Copy link
Copy Markdown
Contributor Author

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

brodo commented Mar 14, 2023

Copy link
Copy Markdown
Contributor Author

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

@brodo

brodo commented Mar 29, 2023

Copy link
Copy Markdown
Contributor Author

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

@jasonsaayman

Copy link
Copy Markdown
Member

@brodo any chance you can look at the conflicts please

@brodo

brodo commented Dec 9, 2024

Copy link
Copy Markdown
Contributor Author

@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

brodo commented Dec 9, 2024

Copy link
Copy Markdown
Contributor Author

@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

Copy link
Copy Markdown
Member

@brodo could you rebase pls

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

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

Comment thread lib/core/AxiosError.js Resolved
Comment thread test/specs/core/AxiosError.spec.js Resolved
Comment thread test/specs/core/AxiosError.spec.js Resolved
Comment thread test/specs/cancel/CanceledError.spec.js Resolved
Comment thread test/specs/cancel/CanceledError.spec.js Resolved
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

brodo commented Nov 8, 2025

Copy link
Copy Markdown
Contributor Author

@jasonsaayman done!

@jasonsaayman jasonsaayman left a comment

Copy link
Copy Markdown
Member

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

None yet

Projects

No open projects
Status: Done

Development

Successfully merging this pull request may close these issues.

4 participants