-
-
Notifications
You must be signed in to change notification settings - Fork 69.4k
Gateway LaunchAgent plist loses custom NODE_OPTIONS after openclaw update #22663
Description
Summary
openclaw update regenerates the LaunchAgent plist (~/Library/LaunchAgents/ai.openclaw.gateway.plist) from scratch, wiping out any custom EnvironmentVariables entries. There's no config path to persist custom env vars across updates.
This is a problem because Node.js 22+ requires workarounds for broken IPv6 dual-stack behavior on networks where IPv6 is unreachable. Without the workaround, the gateway's Telegram channel (and likely any outbound HTTPS to hosts with AAAA records) fails with "Network request for '...' failed!" / ETIMEDOUT.
Environment
- OpenClaw: 2026.2.19-2 (stable, npm)
- Node.js: v24.4.0
- macOS: 26.2 (arm64)
- Gateway: LaunchAgent (
ai.openclaw.gateway)
Steps to reproduce
- Have a network where IPv6 is not fully routable (common on residential networks)
- Add
NODE_OPTIONSto the gateway plist:<key>NODE_OPTIONS</key> <string>--dns-result-order=ipv4first --no-network-family-autoselection</string>
- Verify Telegram works:
openclaw health→Telegram: ok - Run
openclaw update(even if already on the latest version) openclaw health→Telegram: failed (unknown) - fetch failed
Root cause
Node.js 22+ enables autoSelectFamily by default, which tries IPv6 and IPv4 connections simultaneously. When IPv6 is unreachable (EHOSTUNREACH), the fallback to IPv4 is broken — the IPv4 attempt also times out (ETIMEDOUT), even though direct IPv4 TCP connections succeed.
Evidence:
curl https://api.telegram.org/bot.../getMe→ works (system networking handles fallback correctly)node -e "fetch('https://api.telegram.org/...')"→ETIMEDOUT(both IPv4 and IPv6 fail)node -e "net.connect(443, '149.154.166.110', ...)"→ works (raw TCP to IPv4 is fine)NODE_OPTIONS="--dns-result-order=ipv4first --no-network-family-autoselection" node -e "fetch(...)"→ works
Suggested fix
One or more of:
- Persist custom env vars: Support a config path like
gateway.launchAgent.env(orgateway.nodeOptions) that gets merged into the plist on update/regeneration. - Detect and apply the workaround automatically: If the gateway detects
ETIMEDOUTon Telegram/outbound HTTPS and IPv6 is unreachable, log a hint or auto-set--no-network-family-autoselection. - Set
--no-network-family-autoselectionby default: SinceautoSelectFamilyis known to be problematic on many networks, the gateway could default to disabling it in the generated plist.
Current workaround
Manually patch the plist after each update:
# Add to EnvironmentVariables in ~/Library/LaunchAgents/ai.openclaw.gateway.plist:
<key>NODE_OPTIONS</key>
<string>--dns-result-order=ipv4first --no-network-family-autoselection</string>
# Then restart:
openclaw gateway restart