Repository navigation
Fix retries on connection errors reported by request.end() - #1
Merged
Merged
Conversation
Backport of sindresorhus#2470 to v11. Fixes sindresorhus#2469. Node.js 24.20.0 (nodejs/node#64847) calls `ClientRequest#end()` callbacks with the error that prevented the flush. `_final` forwarded it as a stream error while a retry was scheduled: the promise rejected with `ERR_SOCKET_CLOSED_BEFORE_CONNECTION`, retries stopped, and the pending retry threw `The onCancel handler was attached after the promise settled` plus the retried request's error as uncaught exceptions. Route the error through `_beforeError` so it is deduplicated with the request `error` event and handled by the retry logic. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01VZiY7VMgg1nEMkCezwMXEC
Builds and runs test/retry.ts on Node.js LTS and latest, where the request.end() retry regression from nodejs/node#64847 shows up. Dependencies are resolved as of 2021-06-15 because there is no lockfile and newer dev dependencies do not compile with TypeScript 4.0.3. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01VZiY7VMgg1nEMkCezwMXEC
Kikobeats
force-pushed
the
v11-fix-end-callback-retry
branch
from
September 14, 2026 20:50
e1a387b to
4e340e7
Compare
This was referenced Sep 14, 2026
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.
Backport of sindresorhus#2470 to v11. Fixes sindresorhus#2469 for got v11. Upstream won't release this fix for v11.
Problem
Node.js 24.20.0 includes nodejs/node#64847:
ClientRequest#end(callback)now callscallbackwith the error that stopped the flush. Before,callbackwas a'finish'listener and never ran on failure._finalpassed that error tocallback(error), so the gotRequestemitted'error'while a retry was already scheduled. The result on Node.js 24.20.0, for any retryable connection error (ENOTFOUND,ECONNREFUSED, ...):ERR_SOCKET_CLOSED_BEFORE_CONNECTIONinstead of the real error.The onCancel handler was attached after the promise settledas an uncaught exception.uncaughtException.Fix
In
_final, an error reported byend()goes throughthis._beforeError(error)and_finalreturns without callingcallback, same as sindresorhus#2470._beforeErrorignores a second error, so the failure is handled once: whichever of the request's'error'event and theend()callback comes first goes to the retry logic.Tests
Added to
test/retry.ts:calculateDelay,beforeRetry(options, error), streams retrying through'retry',process.nextTicksince v11 supports Node.js >=10.19):end()callback receives it: 3 attempts,ECONNREFUSED,beforeErrorruns onceend()callback receives the error: it still retriesend()error succeedsend()error doesn't emit'finish'on the stream before the retryECONNREFUSED.Results:
test/retry.tswith the fix, Node.js 16 / 24.19.0 / 24.20.0xoon the changed fileshtml-gettest/index.json Node.js 24.20.0 using this buildgot@11.8.6The failures on Node.js 24.20.0 are the 2020-era tests on modern Node;
progress.tsandstream.tscrash there with and without the fix, which is why those files were also compared on Node.js 16 (221 pass, 0 fail across stream, progress, cache, cancel, timeout, retry, post, hooks and promise).CI
Adds
.github/workflows/test.yml(v11 only had Travis). Onv11pushes and pull requests it builds and runstest/retry.tson Node.js LTS and latest. First run: 28 of 28 pass on both, Node.js 24.20.0 (LTS) and 26.8.2 (latest).The full suite isn't run in CI because the 2020-era tests fail on modern Node.js without the fix too (63 failures on Node.js 24.20.0); the Node.js 10/12/14 jobs failed too, on old environment issues in agent/https tests. The four mocked regression tests fail without the fix on any Node.js version, so this job catches a regression.
Build setup
There's no lockfile, and current dev dependencies don't compile with TypeScript 4.0.3. To reproduce:
🤖 Generated with Claude Code
https://claude.ai/code/session_01VZiY7VMgg1nEMkCezwMXEC