Skip to content

fix(core): normalize autoSelectFamily timeout AggregateError#5329

Merged
metcoder95 merged 1 commit into
nodejs:mainfrom
youcefzemmar:fix/sensitivity-to-order-of-connection-errors
May 29, 2026
Merged

fix(core): normalize autoSelectFamily timeout AggregateError#5329
metcoder95 merged 1 commit into
nodejs:mainfrom
youcefzemmar:fix/sensitivity-to-order-of-connection-errors

Conversation

@youcefzemmar
Copy link
Copy Markdown
Contributor

What

In lib/core/connect.js, when the socket's error event fires with an AggregateError from net.connect's autoSelectFamily exhaustion, wrap it as a ConnectTimeoutError if any inner error (or the aggregate itself) carries code: 'ETIMEDOUT'. Message format matches the existing onConnectTimeout output (attempted addresses + timeout). Original aggregate preserved on .cause.

Why

The error reaching the dispatcher callback used to depend on which timer won the race:

  • if undici's connectTimeout fired first → ConnectTimeoutError
  • if Node's per-family attempt timer fired first → raw AggregateError

That ordering sensitivity is what #5092 reports. Single-error paths (e.g. one ECONNREFUSED) are untouched, so the connect-errconnect.js strict-equality assertion still holds.

Testing

  • npx borp -p "test/connect-timeout.js" — green (new test included)
  • npx borp -p "test/connect-errconnect.js" — green (single-error path unchanged)
  • npx borp -p "test/node-test/autoselectfamily.js" — green
  • eslint clean on changed files

test/connect-pre-shared-session.js fails with ERR_SSL_EE_KEY_TOO_SMALL on main too — pre-existing environment issue unrelated to this change.

Notes

Some callers may rely on receiving the raw AggregateError. The original is still accessible via error.cause, and the docs note this. Non-timeout aggregates (e.g. all ECONNREFUSED) are left untouched.

Fixes #5092.

When `autoSelectFamily` exhausts all attempts with timeouts, `net.connect`
raises an `AggregateError` whose surfacing previously depended on whether
Node's family-attempt timer or undici's `connectTimeout` won the race.
Wrap the aggregate as a `ConnectTimeoutError` when any inner error is
ETIMEDOUT (or the aggregate itself carries the code) so callers see the
same error shape regardless of ordering. The original `AggregateError`
is preserved on `.cause`.

Fixes nodejs#5092.
@youcefzemmar youcefzemmar marked this pull request as ready for review May 27, 2026 14:12
Copy link
Copy Markdown
Member

@mcollina mcollina left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

lgtm

@codecov-commenter
Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 92.59259% with 2 lines in your changes missing coverage. Please review.
✅ Project coverage is 93.21%. Comparing base (f049730) to head (942c21e).
⚠️ Report is 5 commits behind head on main.

Files with missing lines Patch % Lines
lib/core/connect.js 92.59% 2 Missing ⚠️
Additional details and impacted files
@@           Coverage Diff           @@
##             main    #5329   +/-   ##
=======================================
  Coverage   93.21%   93.21%           
=======================================
  Files         110      110           
  Lines       36598    36623   +25     
=======================================
+ Hits        34115    34139   +24     
- Misses       2483     2484    +1     

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

@metcoder95 metcoder95 merged commit 2bdc338 into nodejs:main May 29, 2026
38 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

sensitivity to order of connection errors

4 participants