Fetch documentation misleading on Node/Undici GC quirks
Affected URL
https://nodejs.org/en/learn/getting-started/fetch
Describe the issue in detail:
The documentation and examples for getting started with Fetch on Node.js do not make clear the current spec-breaking behavior of Undici to require consumption of the response body.
The first two examples provided on the Fetch page always consume the body, the third actually appears to leak references if the response code indicates a failure due to the body not being consumed and an error being thrown instead.
While the Undici documentation explaning this behavior is currently linked to from the Fetch article, this aspect is buried very far down on that page, and the explanations there are oriented only around situations like trying to just consume headers, not basic error handling like here as presented both in the main Node documentation and in the majority of general Fetch documentation.
The fact that the example given appears to make this same mistake, as well as such leaks being definitely reproducible and surprising to many with similar code (myself included) under the latest LTS v22, would indicate to me this likely warrants at least a brief, dedicated explanation within the same page.
@nodejs/undici
I think this would be a great fix. Happy to review; feel free to tag me on any relevant PRs
Note that it was fixed - there is no need to consume the body anymore, however it would massively improve the performance of the library.
Good spot anyway, I've opened a PR to explain: https://github.com/nodejs/undici/pull/4364.
The reason I stumbled across this in the first place was that I was able to reproduce a very steady memory increase and eventual crash under relatively low consistent load with repeated calls to a 404ing service by not consuming the body under LTS 22 as of a few days ago. Cancelling the body fixed it.
Was this perhaps fixed in upstream Undici but not applicable yet to LTS Node? The relationship there between something being fixed upstream or being extant still for the majority of users has not been clear to me.
It's hard to tell without seeing your code, but I'm pretty sure the generic behavior was fixed (and it's covered by tests). See https://github.com/nodejs/undici/blob/v6.x/test/fetch/fire-and-forget.js and https://github.com/nodejs/undici/blob/v6.x/test/fetch/fetch-leak.js: those are from the v6.x which is the one shipped by Node 22.
Note that the GC is non-deterministic, so under some load you could still get a memory leak behavior because it has not had time to do pass through the data.
Try increasing the memory size, and if not feel free to open an issue with the reproduction.