Describe the bug
When a request is aborted (or fails with a network error) after the response headers have already been received, happy-dom does not run the specification's "request error steps" correctly:
readystatechange is dispatched after abort/error and loadend, instead of immediately after the ready state changes.
- The previously received response (
status, response headers, partially accumulated body) is never discarded, so xhr.status, xhr.getAllResponseHeaders() and similar still report data from the failed request even though the request state has moved to unsent/done.
In a real browser, the request error steps set the response to a network error and fire readystatechange before the abort/error/loadend events, so none of the failed request's data remains observable afterward.
To Reproduce
Steps to reproduce the behavior:
- Create an
XMLHttpRequest against an endpoint that responds with headers immediately but streams the body slowly.
- Wait until the response headers have arrived (readyState 2,
xhr.status already reflects e.g. 200).
- Call
xhr.abort() before the body finishes.
- Inspect
xhr.status, xhr.getAllResponseHeaders() and the order events were received in.
const xhr = new XMLHttpRequest();
const events = [];
['readystatechange', 'abort', 'loadend'].forEach((type) =>
xhr.addEventListener(type, () => events.push(type))
);
xhr.open('GET', '/slow-body');
xhr.send();
// once headers have arrived:
xhr.abort();
// events fires ['abort', 'loadend', 'readystatechange'] - should be
// ['readystatechange', 'abort', 'loadend'].
// xhr.status still reports 200 and xhr.getAllResponseHeaders() still
// returns the aborted response's headers, even though the request was
// aborted and readyState is back to unsent.
https://stackblitz.com/edit/happy-dom-wrong-event-order?file=index.js
Expected behavior
On abort or network error, happy-dom should:
- Reset the response to a network error (so
status becomes 0, headers/body/responseURL are cleared) before dispatching any events.
- Dispatch
readystatechange first, then abort/error, then loadend.
Device and details:
- OS: MacOS 26.6.1
- Node version: 24.19.0
- Package version: 20.11.2
Additional context
Relevant spec section: https://xhr.spec.whatwg.org/#request-error-steps
Describe the bug
When a request is aborted (or fails with a network error) after the response headers have already been received, happy-dom does not run the specification's "request error steps" correctly:
readystatechangeis dispatched afterabort/errorandloadend, instead of immediately after the ready state changes.status, response headers, partially accumulated body) is never discarded, soxhr.status,xhr.getAllResponseHeaders()and similar still report data from the failed request even though the request state has moved tounsent/done.In a real browser, the request error steps set the response to a network error and fire
readystatechangebefore theabort/error/loadendevents, so none of the failed request's data remains observable afterward.To Reproduce
Steps to reproduce the behavior:
XMLHttpRequestagainst an endpoint that responds with headers immediately but streams the body slowly.xhr.statusalready reflects e.g. 200).xhr.abort()before the body finishes.xhr.status,xhr.getAllResponseHeaders()and the order events were received in.https://stackblitz.com/edit/happy-dom-wrong-event-order?file=index.js
Expected behavior
On abort or network error, happy-dom should:
statusbecomes0, headers/body/responseURLare cleared) before dispatching any events.readystatechangefirst, thenabort/error, thenloadend.Device and details:
Additional context
Relevant spec section: https://xhr.spec.whatwg.org/#request-error-steps