Repository navigation
fix(xhr): reject navigation-canceled requests as ECONNABORTED - #11094
Merged
jasonsaayman merged 8 commits intoJul 30, 2026
Merged
jasonsaayman merged 8 commits into
jasonsaayman merged 8 commits into
Conversation
onerror and onabort are what reject a request that never received a response, and they null the request handle, which is the only thing that makes onloadend bail. Firefox 152 stopped firing either of them for requests canceled by a document navigation, emitting only readystatechange and loadend, so onloadend became the only handler that runs and settle() resolved the request through its !response.status branch. Callers got a successful response carrying status 0 and an empty body, which then fails any JSON parsing or schema validation downstream. Firefox 151 raised abort for the same cancellation, which this adapter reports as ECONNABORTED, so rejecting with that code leaves the outcome an application sees unchanged across the update. Mozilla confirmed the old behavior on the bug, and the patch that changed it is titled "Fires readystatechange and loadend intead of abort". The file: exception is keyed on both the request URL and responseURL. A page loaded from file: may request a relative path that carries no scheme, and responseURL is unavailable in some of the environments where a successful file: read is reported as status 0. Ref: https://bugzilla.mozilla.org/show_bug.cgi?id=1505389
Contributor
There was a problem hiding this comment.
All reported issues were addressed across 3 files
Reply with feedback, questions, or to request a fix.
Re-trigger cubic
Greptile SummaryRejects status-zero XHR completions as aborted while preserving successful
Confidence Score: 5/5The PR appears safe to merge. No blocking failures remain.
What T-Rex did
|
| Filename | Overview |
|---|---|
| lib/adapters/xhr.js | Adds status-zero rejection and correctly applies browser-style URL preprocessing before the file-protocol exemption. |
| lib/helpers/normalizeURLForProtocolCheck.js | Extracts reusable WHATWG-style preprocessing for protocol checks. |
| lib/core/buildFullPath.js | Replaces the local URL-normalization implementation with the shared helper without changing behavior. |
| tests/browser/requests.browser.test.js | Adds browser-level coverage for status-zero rejection and responseURL-based file reads. |
| tests/unit/adapters/xhr.test.js | Covers file-origin fallback, explicit network URLs with browser-trimmed prefixes, and unconditional aborted-request rejection. |
Reviews (5): Last reviewed commit: "fix(xhr): normalize URL before status 0 ..." | Re-trigger Greptile
A relative request URL carries no scheme, so a read from a page served over file: was only exempted from the status-0 rejection when the engine exposed responseURL. Fall back to the scheme of platform.origin, which a relative URL inherits, so such reads keep resolving when responseURL is unavailable. Unit tests drive the real adapter with stubbed globals to pin all three exemption sources and both rejection paths.
…gation-cancel # Conflicts: # PRE_RELEASE_CHANGELOG.md
…gation-cancel # Conflicts: # PRE_RELEASE_CHANGELOG.md
21 tasks done
This was referenced Oct 4, 2026
markharding
pushed a commit
to futo-org/Harbor
that referenced
this pull request
Oct 16, 2026
This PR contains the following updates: | Package | Change | [Age](https://docs.renovatebot.com/merge-confidence/) | [Confidence](https://docs.renovatebot.com/merge-confidence/) | |---|---|---|---| | [axios](https://axios-http.com) ([source](https://github.com/axios/axios)) | [`1.18.1` → `1.20.0`](https://renovatebot.com/diffs/npm/axios/1.18.1/1.20.0) |  |  | --- >⚠️ **Warning** > > Some dependencies could not be looked up. Check the [Dependency Dashboard](issues/99) for more information. --- ### Release Notes <details> <summary>axios/axios (axios)</summary> ### [`v1.20.0`](https://github.com/axios/axios/releases/tag/v1.20.0) [Compare Source](axios/axios@v1.19.0...v1.20.0) #### v1.20.0 — August 19, 2026 This release hardens runtime option handling, adds RFC 9110 status-code aliases, fixes Node.js and XHR reliability issues, and refreshes project tooling and documentation. ####⚠️ Breaking Changes & Deprecations - HTTP Status Naming: Added ContentTooLarge (413) and UnprocessableContent (422), while retaining PayloadTooLarge and UnprocessableEntity as backward-compatible deprecated aliases. ([#​11082](axios/axios#11082)) #### 🔒 Security Fixes - Runtime Option Handling: Hardened behavioral configuration reads against shared and foreign prototype pollution and normalized unsafe interceptor replacement objects. This also clarifies Fetch redirect and custom implementation behavior, HTTP/2 DNS and proxy handling, CIDR-based NO_PROXY matching, and malformed data URI rejection; see the PR for documented compatibility effects. ([#​11141](axios/axios#11141)) #### 🐛 Bug Fixes - Interceptor Lifecycle: Prevented unbounded handler-array growth by trimming trailing ejected interceptors without changing iteration semantics, and kept interceptor operations safe when the public handlers field is nullish. ([#​11087](axios/axios#11087), [#​11118](axios/axios#11118)) - Request Error Preservation: Prevented custom Error.prepareStackTrace implementations that return non-string values from replacing the original request failure with an unrelated TypeError. ([#​11109](axios/axios#11109)) - XHR Reliability: Navigation-canceled requests now reject with ECONNABORTED instead of resolving with status 0, while successful downloads flush their final progress callback during the live loadend dispatch. ([#​11094](axios/axios#11094), [#​11121](axios/axios#11121)) - Node.js Socket Memory: Removed request-context retention from per-socket error listeners, preventing completed response data from being pinned for the lifetime of pooled keep-alive sockets. ([#​11091](axios/axios#11091)) - Core Methods and HTTP Errors: Prevented structural method-header buckets from leaking into outgoing headers, standardized invalid DNS lookup and httpVersion failures as AxiosError.ERR_BAD_OPTION_VALUE, and corrected the timeoutErrorMessage merge strategy. ([#​11096](axios/axios#11096)) #### 🔧 Maintenance & Chores - Dependencies: Updated fast-uri, postcss, js-yaml, mocha, development-tooling groups, and GitHub Actions dependencies. ([#​11092](axios/axios#11092), [#​11098](axios/axios#11098), [#​11099](axios/axios#11099), [#​11106](axios/axios#11106), [#​11107](axios/axios#11107), [#​11122](axios/axios#11122), [#​11123](axios/axios#11123), [#​11126](axios/axios#11126), [#​11127](axios/axios#11127), [#​11133](axios/axios#11133), [#​11140](axios/axios#11140), [#​11143](axios/axios#11143), [#​11144](axios/axios#11144)) - Documentation: Applied the v1.19.0 documentation updates, added the missing fs import to the README stream example, introduced localized global search, and repaired the interceptor test link. ([#​11101](axios/axios#11101), [#​11113](axios/axios#11113), [#​11097](axios/axios#11097), [#​11119](axios/axios#11119)) - Sponsorship: Updated sponsorship links and data and added ScrapingBee as a sponsor. ([#​11124](axios/axios#11124), [#​11136](axios/axios#11136), [#​11137](axios/axios#11137)) - CI and Release: Switched ESM smoke tests to locked dependencies and synchronized package and runtime version metadata for v1.20.0. ([#​11128](axios/axios#11128), [#​11152](axios/axios#11152)) #### 🌟 New Contributors We are thrilled to welcome our new contributors. Thank you for helping improve axios: - [@​yens1](https://github.com/yens1) ([#​11109](axios/axios#11109)) - [@​Sasireddy001](https://github.com/Sasireddy001) ([#​11113](axios/axios#11113)) - [@​ari-token-security](https://github.com/ari-token-security) ([#​11094](axios/axios#11094)) - [@​timothyokooboh](https://github.com/timothyokooboh) ([#​11097](axios/axios#11097)) - [@​gi9439041-png](https://github.com/gi9439041-png) ([#​11119](axios/axios#11119)) - [@​Hashim1999164](https://github.com/Hashim1999164) ([#​11082](axios/axios#11082)) - [@​v-dev-cl](https://github.com/v-dev-cl) ([#​11091](axios/axios#11091)) - [@​r0h1tb](https://github.com/r0h1tb) ([#​11118](axios/axios#11118)) - [@​ostapondo](https://github.com/ostapondo) ([#​11121](axios/axios#11121)) Full Changelog (<axios/axios@v1.19.0...v1.20.0>) ### [`v1.19.0`](https://github.com/axios/axios/blob/HEAD/CHANGELOG.md#v1190--July-22-2026) [Compare Source](axios/axios@v1.18.1...v1.19.0) This release raises the form-data security floor, adds configuration and type-system capabilities, and fixes NO_PROXY matching, interceptor errors, progress reporting, and serialization edge cases. </details> --- ### Configuration 📅 **Schedule**: (UTC) - Branch creation - "before 9am on tuesday" - Automerge - At any time (no schedule defined) 🚦 **Automerge**: Disabled by config. Please merge this manually once you are satisfied. ♻ **Rebasing**: Whenever PR becomes conflicted, or you tick the rebase/retry checkbox. 🔕 **Ignore**: Close this PR and you won't be reminded about this update again. --- - [ ] <!-- rebase-check -->If you want to rebase/retry this PR, check this box --- This PR has been generated by [Mend Renovate CLI](https://github.com/renovatebot/renovate). <!--renovate-debug:eyJjcmVhdGVkSW5WZXIiOiI0NC4xMzMuMCIsInVwZGF0ZWRJblZlciI6IjQ0LjE2NC41IiwidGFyZ2V0QnJhbmNoIjoiZGV2ZWxvcCIsImxhYmVscyI6WyJkZXBlbmRlbmNpZXMiLCJyZW5vdmF0ZSJdfQ==--> Reviewed-on: https://code.futo.org/harbor/harbor/pulls/1808
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Firefox 152 stopped firing
errorandabortfor XHRs canceled by a document navigation, emitting onlyreadystatechangeandloadend(bugzilla 1505389, and Mozilla upstreamed a conformance test for it in wpt#59603). Sinceonerror/onabortare what reject and null the request handle, and that null is the only thing makingonloadendbail,onloadendbecame the only handler that runs.settle()then resolved the canceled request through its!response.statusbranch, so callers received a successful response carryingstatus: 0and an empty body.This rejects that case in the XHR adapter instead, with
ECONNABORTED/Request aborted. That is the same error Firefox 151 produced for the identical cancellation, so an application sees no change in outcome across the Firefox update. Mozilla confirmed the old behavior on the bug ("only the onabort callback is called instead of onerror") and the patch that changed it is titled "Fires readystatechange and loadend intead of abort".lib/core/settle.jsis deliberately untouched, because it is shared with the fetch adapter where an opaqueno-corsresponse legitimately carries status 0.Patch-level behavior change, not a breaking API change. Browser requests whose response reaches
loadendwith status 0 previously resolved with an empty body and now reject withECONNABORTED/Request aborted. Two consequences worth stating explicitly:file:, which some environments report as status 0 on success, still resolve. The exemption looks at the scheme of the request URL, at the scheme of the page origin for relative URLs (which inherit it), and atresponseURLwhere implemented.validateStatus. It never consulted it for status 0 anyway, since!response.statusshort-circuits ahead of it, andonerror/onabortreject unconditionally for the same reason: there is no response to validate.This is XHR-only. The fetch and Node HTTP adapters do not have the equivalent failure mode, and are unchanged.
Linked issue
Closes #11093
Changes
lib/adapters/xhr.js: reject withECONNABORTEDwhenonloadendis reached with status 0, excludingfile:reads.tests/browser/requests.browser.test.js: a rejection test for the non-file:case, and a resolve test for a relativefile:read, placed next to the existing file-protocol test.tests/unit/adapters/xhr.test.js: unit tests that drive the real adapter in Node with stubbed globals, covering the relativefile:read withoutresponseURLraised in review, plus reject and resolve controls for the other exemption sources.PRE_RELEASE_CHANGELOG.md: entry under Bug Fixes.Checklist
index.d.tsandindex.d.cts) - N/A, no public API change. The existingECONNABORTEDdescription ("timed out ... or aborted by the browser or its plugin") already covers this case.Validation
Run against this branch, on top of
v1.xat 5097193 (1.19.0):npm run test:vitest:unithas 2 failures intests/unit/adapters/fetch.test.js, both of which reproduce identically on a pristine checkout ofv1.x, so they are unrelated to this change.Each new assertion was mutation-tested: removing the guard fails the rejection tests, and dropping any of the three
file:exemption sources fails a corresponding test.Note that Playwright's bundled Firefox is 151, which predates the behavior being fixed, so the regression cannot be reproduced through the browser runner. The tests use the existing
MockXMLHttpRequest, whosefinish()already fires onlyonloadend, which is exactly the Firefox 152 shape. The browser harness also cannot serve a page overfile:, so the page-origin exemption is covered by the unit tests instead, which stub the globals before importing axios so the real adapter runs with afile:origin.🏄 Investigated and written with AI assistance, reviewed before opening.
Summary by cubic
Reject navigation-canceled XHRs with status 0 as
ECONNABORTEDto prevent empty successes on Firefox 152+. Successfulfile:reads still resolve, including relative paths inferred from the page’sfile:origin or viaresponseURL.Description
loadendwith status 0 unless it’s afile:read (checks normalized request URL, page origin for relative URLs, andresponseURL).normalizeURLForProtocolCheckto match WHATWG URL preprocessing; used by XHR protocol checks and imported bybuildFullPath.lib/core/settle.jsunchanged to avoid impacting fetch’s opaqueno-corsresponses.validateStatus, since no response was received.Testing and Impact
file:status 0; resolve absolute/relativefile:reads, including viaresponseURL.validateStatusis not called./docs/browser/XHR section to note status 0 onloadendrejects asECONNABORTED, except successfulfile:reads; clarifyvalidateStatusis not applied without a response.Written for commit 27b9d97. Summary will update on new commits.