Skip to content

Fix AggregateError crashes on Node.js 20+ caused by Happy Eyeballs (autoSelectFamily)#61

Closed
dirkwa wants to merge 1 commit intoSignalK:masterfrom
dirkwa:fix/node20-autoselectfamily-workaround
Closed

Fix AggregateError crashes on Node.js 20+ caused by Happy Eyeballs (autoSelectFamily)#61
dirkwa wants to merge 1 commit intoSignalK:masterfrom
dirkwa:fix/node20-autoselectfamily-workaround

Conversation

@dirkwa
Copy link
Copy Markdown
Contributor

@dirkwa dirkwa commented Jan 23, 2026

Summary

  • Add workaround for Node.js 20+ "Happy Eyeballs" (RFC 6555) causing AggregateError in HTTP libraries

Problem

Node.js 20+ enables autoSelectFamily by default, which implements RFC 6555 "Happy Eyeballs" - attempting IPv4 and IPv6 connections simultaneously. When both connection attempts fail, Node.js throws an AggregateError.

Libraries using @cypress/request (including node-telegram-bot-api used by node-red-contrib-telegrambot) don't handle AggregateError properly, causing unhandled exceptions and plugin crashes.

Example error:

AggregateError
    at internalConnectMultiple (node:net:1121:18)
    at afterConnectMultiple (node:net:1688:7)

Solution

Disable autoSelectFamily at plugin initialization by calling net.setDefaultAutoSelectFamily(false). This is placed at the very top of index.js before any dependencies are loaded, ensuring it applies globally to all network connections.

References

Testing

Tested on SignalK server running Node.js v24.13.0 with node-red-contrib-telegrambot. Before the fix, continuous AggregateError crashes occurred. After the fix, no errors and stable operation.

Disable autoSelectFamily (Happy Eyeballs RFC 6555) to prevent
AggregateError crashes in Node-RED nodes using @cypress/request
(e.g., node-red-contrib-telegrambot).

Node.js 20+ enables autoSelectFamily by default, which tries IPv4
and IPv6 connections simultaneously. When both fail, it throws
AggregateError which older HTTP libraries don't handle properly.

Fixes issues with:
- node-telegram-bot-api (uses @cypress/request)
- Other Node-RED nodes using deprecated request libraries

References:
- yagop/node-telegram-bot-api#1193
- nodejs/node#46790
@sbender9
Copy link
Copy Markdown
Member

sbender9 commented Jan 23, 2026

Don't love this because it is global, right? This will affect the server and other plugins.

If we want to turn this off, we should probably do it in the server.

Or you could do it in a function node?

What do you think @tkurki

@dirkwa
Copy link
Copy Markdown
Contributor Author

dirkwa commented Jan 24, 2026

@sbender9

I understand your concerns, so we should address this properly. Node-Red will be a show stopper to lift SignalK to node 24.

You have not been a lot involved in the Universal Installer that runs podman containers.
I am currently working on a PR that it is all controlled "in the background" from the signalk-server.

My idea would be to put the node-red-plugin into a container and during App Store install to spin it up.

Architecture Sketch

┌─────────────────────────────────────────────────┐
│  Pod: signalk                                   │
│                                                 │
│  ┌─────────────────┐    ┌────────────────────┐  │
│  │ signalk-server  │◄───│ node-red           │  │
│  │                 │ WS │                    │  │
│  │ localhost:3000  │───►│ Uses existing      │  │
│  │                 │    │ node-red-contrib-  │  │
│  │                 │    │ signalk nodes      │  │
│  └─────────────────┘    └────────────────────┘  │
└─────────────────────────────────────────────────┘

Node-RED just uses the existing node-red-contrib-signalk nodes pointing at localhost:3000. No special integration needed.

Why This Is a Great Fit

Complete process isolation - Node-RED runs in its own container with its own Node.js process. The net.setDefaultAutoSelectFamily(false) stays contained. SignalK core and other plugins are completely unaffected.

Other benefits you get for free:

  • Node-RED can have its own Node.js version (pin to whatever works best)
  • Memory limits / resource isolation
  • Easier upgrades (swap container image, done)
  • Node-RED's npm dependencies can't conflict with SignalK's
  • Crash isolation - Node-RED dying doesn't take down SignalK
  • Security - Node-RED flows can be sandboxed from the host

If this interests you than I am more than happy to share additional details.
Feel free to close this PR.

@sbender9
Copy link
Copy Markdown
Member

sbender9 commented Jan 25, 2026

The current node-red contrib does not work in a separate node-red process. It uses the plugin apis. Some of the functionality is not available externally.

@dirkwa
Copy link
Copy Markdown
Contributor Author

dirkwa commented Jan 25, 2026

The current node-red contrib does not work in a separate node-red process. It uses the plugin apis. Some of the functionality is not available externally.

I am fully aware of this, it would be a refactoring to a containerized runtime. Would you be open minded for this, if I give it a try?

@sbender9
Copy link
Copy Markdown
Member

The current node-red contrib does not work in a separate node-red process. It uses the plugin apis. Some of the functionality is not available externally.

I am fully aware of this, it would be a refactoring to a containerized runtime. Would you be open minded for this, if I give it a try?

yes, but I think we need two versions of the nodes or to make the nodes detect when running embedded and use the plugin api's, and one that uses WebSockets. Nodes like input-handler and send-nmea2000/0183 won't work unless some support is added to the server to do these over WS.

@sbender9
Copy link
Copy Markdown
Member

This issue is only problem for node-red-contrib-telegrambot or for node-red in general? I thought I tested with v24.

@dirkwa
Copy link
Copy Markdown
Contributor Author

dirkwa commented Jan 25, 2026

This issue is only problem for node-red-contrib-telegrambot or for node-red in general? I thought I tested with v24.

I have not tested everything in detail tbo. That was the first thing that I saw was broken.

yes, but I think we need two versions of the nodes or to make the nodes detect when running embedded and use the plugin api's, and one that uses WebSockets. Nodes like input-handler and send-nmea2000/0183 won't work unless some support is added to the server to do these over WS.

Thanks for the hint. I will look into it mid Feb I think, after returning from my trip.

@tkurki
Copy link
Copy Markdown
Member

tkurki commented Jan 25, 2026

No, let’s not start changing global node level defaults for a single add on of a plugin.

Why would this even crop up now if it’s been in Node since 20?

Remote SK nodes is 100% separate issue, let’s try to keep discussion organised. End users do read this stuff and mixing separate things into a mishmash results in misguided advice and confused people. Ask me how I know.

@tkurki tkurki closed this Jan 25, 2026
@tkurki
Copy link
Copy Markdown
Member

tkurki commented Jan 25, 2026

Well, maybe 96% separate.

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.

3 participants