Version
v22.22.0
Platform
Darwin 25.2.0 arm64
Subsystem
http, net
What steps will reproduce the bug?
- Start an HTTP proxy on
127.0.0.1:10808
- Set environment variables:
HTTP_PROXY=http://127.0.0.1:10808
HTTPS_PROXY=http://127.0.0.1:10808
- Run a Node.js application that uses the
ws library to maintain a WebSocket long connection (e.g., Discord gateway via wss://gateway.discord.gg) with NODE_USE_ENV_PROXY=true or --use-env-proxy
- The WebSocket connection will repeatedly disconnect with close codes 1005/1006
How often does it reproduce? Is there a required condition?
100% reproducible. The WebSocket disconnects within minutes to hours (varies by proxy and server). Without --use-env-proxy, the same connection stays stable indefinitely.
What is the expected behavior? Why is that the expected behavior?
WebSocket connections via the ws library should work normally with --use-env-proxy. The proxy interception should either:
- Properly tunnel WebSocket upgrade requests through the HTTP proxy, or
- Not intercept WebSocket connections at all (since
ws uses raw TCP/TLS via http.request() upgrade)
What do you see instead?
When --use-env-proxy is enabled, the proxy agent intercepts http.request() calls used by the ws library for WebSocket upgrades. This causes:
- WebSocket connections to close with code 1005 (no status code) or 1006 (abnormal closure)
- Repeated reconnection attempts that also fail
- The application effectively loses real-time connectivity
Workaround
Instead of --use-env-proxy, use --require=preload.cjs with:
const { EnvHttpProxyAgent, setGlobalDispatcher } = require('undici');
setGlobalDispatcher(new EnvHttpProxyAgent());
This only patches undici's fetch dispatcher without intercepting http.request()/https.request(), so ws library connections work normally while fetch() calls still go through the proxy.
Context
This was discovered while running an application (OpenClaw, an AI agent gateway) that uses:
ws library for Discord WebSocket gateway (long-lived connection)
fetch() for REST API calls and OpenAI embedding API
The --use-env-proxy flag was needed to make fetch() calls go through the proxy, but it broke the WebSocket connection. The workaround above (patching only the undici global dispatcher) solves both needs.
Related
Version
v22.22.0
Platform
Darwin 25.2.0 arm64
Subsystem
http, net
What steps will reproduce the bug?
127.0.0.1:10808wslibrary to maintain a WebSocket long connection (e.g., Discord gateway viawss://gateway.discord.gg) withNODE_USE_ENV_PROXY=trueor--use-env-proxyHow often does it reproduce? Is there a required condition?
100% reproducible. The WebSocket disconnects within minutes to hours (varies by proxy and server). Without
--use-env-proxy, the same connection stays stable indefinitely.What is the expected behavior? Why is that the expected behavior?
WebSocket connections via the
wslibrary should work normally with--use-env-proxy. The proxy interception should either:wsuses raw TCP/TLS viahttp.request()upgrade)What do you see instead?
When
--use-env-proxyis enabled, the proxy agent interceptshttp.request()calls used by thewslibrary for WebSocket upgrades. This causes:Workaround
Instead of
--use-env-proxy, use--require=preload.cjswith:This only patches undici's fetch dispatcher without intercepting
http.request()/https.request(), sowslibrary connections work normally whilefetch()calls still go through the proxy.Context
This was discovered while running an application (OpenClaw, an AI agent gateway) that uses:
wslibrary for Discord WebSocket gateway (long-lived connection)fetch()for REST API calls and OpenAI embedding APIThe
--use-env-proxyflag was needed to makefetch()calls go through the proxy, but it broke the WebSocket connection. The workaround above (patching only the undici global dispatcher) solves both needs.Related
ws