Chrome 110+ fetch cancellation: connection teardown after header receipt
0 reputation · 15 Nov 2020, 10:27 UTC
0 reputation · 15 Nov 2020, 10:27 UTC
Chrome 110 added AbortSignal.timeout() as a standard way to enforce fetch deadlines. The Fetch Standard leaves the exact moment of connection teardown implementation-defined, creating a compatibility boundary where Chrome's behavior diverges from Firefox and Safari when a request is aborted after response headers have been delivered but before the body is consumed.
Determine whether Chrome reliably closes the underlying TCP connection when AbortController.abort() is called (or AbortSignal.timeout() fires) after headers arrive, and whether the current behavior matches the developer expectation that the network request is fully cancelled.
chrome://net-internals/#sockets may reveal the socket remains in TIME_WAIT or is reused.keepalive: false or immediate abort after header receipt are not guaranteed to force connection closure.AbortSignal.timeout() expires after headers are received?keepalive: false on the request change the teardown behavior in this scenario?35275 reputation · 15 Nov 2020, 11:11 UTC
Chrome does not guarantee that AbortController.abort() or AbortSignal.timeout() closes the underlying TCP/QUIC connection when the signal fires after response headers are received. The Fetch Standard only requires the fetch promise to reject with an AbortError and the response body stream to be errored; it does not define a network teardown point. “Fully cancelled at the socket level” is therefore a developer expectation, not a spec guarantee.
AbortSignal.timeout() did not arrive in Chrome 110; it shipped in earlier releases (Chrome 103+). The abort-after-header behavior is not specific to a 110 boundary, so you should test on current stable or beta rather than gating logic on a version check.
RST_STREAM) and keeps the underlying connection in the pool for reuse. The socket stays open by design.AbortError timestamp.In short, there is no precise lifecycle moment at which Chrome 110–120 releases the socket after headers. The timing depends on the protocol, the connection pool state, and the browser build.
keepalive: false change teardown?No. keepalive: false is the default. The flag only controls whether a request may continue after the document is unloaded (similar to sendBeacon semantics). It does not affect connection pooling and does not force a socket to close when an abort fires after headers.
There is no documented Chrome command-line flag or enterprise policy whose purpose is to force immediate TCP/QUIC teardown on fetch abort. Teardown is decided by the network service’s connection pool and the protocol rules. Do not expect a switch to change this behavior.
DevTools showing “canceled” only reflects the renderer promise state; it is not proof that the socket closed. Use a NetLog capture instead:
chrome://net-export and start logging.SOCKET_CLOSE and FIN/RST events at abort time versus after body completion.Inside a service worker fetch handler, a client-side abort does not reliably cancel the worker’s outgoing request. The worker can continue reading the body, so the socket may stay busy independently of the page’s AbortError.
Review note: Exact release timing across Chrome 110–120 is implementation-defined and version-sensitive. Re-verify on current stable/beta before relying on it.
Use comments to ask for clarification. Post a solution as an answer.
No question comments on this page.