From 822e3e40b4f9287b5a787f5d1dfb3ae7f8a0faa3 Mon Sep 17 00:00:00 2001 From: Alexander Gehres Date: Sat, 14 Feb 2026 16:31:52 +0100 Subject: [PATCH] fix: make AxiosError.message property enumerable (#7392) * fix: make AxiosError.message property enumerable Restores backward compatibility by making the message property enumerable. In v1.13.3, the refactoring to extend native Error made message non-enumerable, breaking code that uses Object.keys(), Object.entries(), or spread operator on AxiosError instances. This fix uses Object.defineProperty to explicitly make the message property enumerable while maintaining the benefits of extending the native Error class. Breaking change introduced in: v1.13.3 (commit 1c6a86d) Affects: Object.keys(), Object.entries(), spread operator, for...in loops * chore: build fix --------- Co-authored-by: Alexander Gehres Co-authored-by: Jay --- lib/core/AxiosError.js | 55 ++++++++++++++++++------------ test/specs/core/AxiosError.spec.js | 22 ++++++++++++ 2 files changed, 55 insertions(+), 22 deletions(-) diff --git a/lib/core/AxiosError.js b/lib/core/AxiosError.js index 60818f2b..14737173 100644 --- a/lib/core/AxiosError.js +++ b/lib/core/AxiosError.js @@ -11,29 +11,40 @@ class AxiosError extends Error { return axiosError; } - /** - * Create an Error with the specified message, config, error code, request and response. - * - * @param {string} message The error message. - * @param {string} [code] The error code (for example, 'ECONNABORTED'). - * @param {Object} [config] The config. - * @param {Object} [request] The request. - * @param {Object} [response] The response. - * - * @returns {Error} The created error. - */ - constructor(message, code, config, request, response) { - super(message); - this.name = 'AxiosError'; - this.isAxiosError = true; - code && (this.code = code); - config && (this.config = config); - request && (this.request = request); - if (response) { - this.response = response; - this.status = response.status; + /** + * Create an Error with the specified message, config, error code, request and response. + * + * @param {string} message The error message. + * @param {string} [code] The error code (for example, 'ECONNABORTED'). + * @param {Object} [config] The config. + * @param {Object} [request] The request. + * @param {Object} [response] The response. + * + * @returns {Error} The created error. + */ + constructor(message, code, config, request, response) { + super(message); + + // Make message enumerable to maintain backward compatibility + // The native Error constructor sets message as non-enumerable, + // but axios < v1.13.3 had it as enumerable + Object.defineProperty(this, 'message', { + value: message, + enumerable: true, + writable: true, + configurable: true + }); + + this.name = 'AxiosError'; + this.isAxiosError = true; + code && (this.code = code); + config && (this.config = config); + request && (this.request = request); + if (response) { + this.response = response; + this.status = response.status; + } } - } toJSON() { return { diff --git a/test/specs/core/AxiosError.spec.js b/test/specs/core/AxiosError.spec.js index 92576b69..17495ad4 100644 --- a/test/specs/core/AxiosError.spec.js +++ b/test/specs/core/AxiosError.spec.js @@ -67,4 +67,26 @@ describe('core::AxiosError', function () { const err = new AxiosError('test', 'foo', {}, {}, { status: 400 }); expect(err.status).toBe(400); }); + + it('should have message property as enumerable for backward compatibility', () => { + const err = new AxiosError('Test error message', 'ERR_TEST', {foo: 'bar'}); + + // Test Object.keys() includes message + const keys = Object.keys(err); + expect(keys).toContain('message'); + + // Test Object.entries() includes message + const entries = Object.entries(err); + const messageEntry = entries.find(([key]) => key === 'message'); + expect(messageEntry).toBeDefined(); + expect(messageEntry[1]).toBe('Test error message'); + + // Test spread operator includes message + const spread = {...err}; + expect(spread.message).toBe('Test error message'); + + // Verify message descriptor is enumerable + const descriptor = Object.getOwnPropertyDescriptor(err, 'message'); + expect(descriptor.enumerable).toBe(true); + }); });