Responses WebSocket connect failures wait through all stream retries before HTTP fallback
Summary
Many users behind proxies, especially in mainland China, see Codex print Reconnecting... 1/5 through 5/5 at the start of a turn before it finally begins responding. A practical workaround reported in #14297 is to define a custom provider with supports_websockets = false, which makes Codex use HTTP/SSE immediately.
I investigated the code path and prepared a small patch in my fork:
- Branch: https://github.com/weidapao/codex/tree/codex/fast-http-fallback-websocket-connect
- Commit: https://github.com/weidapao/codex/commit/2284b7ee5
Root Cause
The default OpenAI provider supports Responses WebSocket transport. When the local/proxy environment cannot carry WebSocket traffic correctly, WebSocket connect fails with timeout/network errors. Today those failures are treated like retryable stream failures, so the turn loop consumes the full stream_max_retries budget before activating HTTP fallback.
This matches user logs from #14297: every attempt is transport="responses_websocket"; after Reconnecting... 5/5, Codex logs falling back to HTTP, then the HTTP Responses request completes quickly.
Proposed Change
Fallback to HTTP/SSE immediately when Responses WebSocket connection setup fails with:
TransportError::TimeoutTransportError::Network(_)
Keep the existing behavior for established stream failures and for explicit 426 Upgrade Required fallback.
The patch adds a small helper:
fn should_fallback_to_http_after_websocket_connect_error(error: &ApiError) -> bool {
matches!(
error,
ApiError::Transport(TransportError::Timeout | TransportError::Network(_))
)
}
and applies it in both WebSocket preconnect/prewarm and normal turn-time WebSocket connection setup.
Why This Helps
Users whose proxies do not support WebSocket/TUN routing should no longer wait through all 5 reconnect attempts before Codex switches to the HTTP path that already works for them. Users with working WebSocket transport should continue using WebSocket as before.
Test Coverage
The fork adds a regression test that simulates a WebSocket handshake timeout and asserts Codex performs only one WebSocket attempt before using HTTP/SSE successfully.
cargo test -p codex-core websocket_fallback_switches_to_http_on_connect_timeout -- --exact
I could not complete the test locally on my Windows machine because the environment is missing the MSVC linker link.exe, but formatting and git diff --check passed locally.
10 Comments
Potential duplicates detected. Please review them and close your issue if it is a duplicate.
Powered by Codex Action
Web sockets provide many performance benefits over HTTP, so we really don't want to use the fallback unless it's really necessary. I don't think that an immediate fallback on first error would serve most customers well.
Is there no way you can configure your proxy to support web socket connections? Which proxy are you using? Perhaps you can work with the maintainers to get this limitation removed?
I am seeing the same pattern in codex: the WebSocket retries through
Reconnecting... 1/5...5/5, then the HTTP fallback works normally.One thing I am trying to understand: does the Responses WebSocket transport currently respect proxy environment variables such as
HTTP_PROXY/HTTPS_PROXY, or the WebSocket-specificWS_PROXY/WSS_PROXY? In my local setup the proxy itself appears to support WebSocket tunneling over HTTP CONNECT, and regular HTTPS traffic through the proxy works, so it is not obvious whether the failing path is the proxy or whether the WS client path is bypassing proxy env handling.If the WebSocket path does not currently share the same proxy handling as the HTTP path, could Codex either add that support or expose a ChatGPT-auth-compatible config option to force HTTPS/SSE transport / disable Responses WebSocket? That would avoid the repeated fixed delay for environments where HTTP fallback is consistently the working path.
环境:Windows 10/11 + ChatGPT OAuth
现象:每次启动 hello 卡 75 秒(5×15s WebSocket 重试)
UI 误导:显示「Timeout waiting for child process to exit」
日志真凶:responses_websocket + stream disconnected - retrying sampling request
workaround:自定义 HTTP-only provider + supports_websockets = false
改进建议:
修 UI 错误文案,别把 WS 失败包装成子进程超时
提供 CLI / config 直接禁用 WebSocket 的开关(不用新建 provider)
缩短 WebSocket 失败重试次数(5×15s = 75s 太长了,2×5s 也够判定)
The same pattern in Codex for the last 3-4 days: the WebSocket retries through Reconnecting... 1/5 ... 5/5, then the HTTP fallback works normally.
Same issue, not fixed, this occurs not only for the first query on startup, but also for every subagent launched right after previous query succeeds (so this issue is definitely state-dependent), essentially adding a delay of 1min+ for every attempt to establish a fresh connection.
According to Codex itself:
Current source opens a direct TCP/TLS connection using tokio_tungstenite::connect_async_tls_with_config without consulting macOS proxy settings or proxy environment variables (source). respect_system_proxy only configures selected HTTP/auth clients.
So probably why ChatGPT for Mac works fine for me but Codex doesn't is because Codex doesn't respect OS proxy for wss.
But according to https://github.com/openai/codex/issues/13041, this can also happen without proxy.
so I doubt this is only a proxy-related issue or just some bugs with server or client side wss implementation.
Some mentioned forcing ipv4 instead of ipv6 might solve the issue: https://github.com/openai/codex/issues/13406#issuecomment-4169251271, but in my case, that does not work.
Also, I think a better timing to try to handshake with server than posting query is when clicking on conversation tab or when first typing query (Google does this anticipatory trick), that may reduce the wait time, giving a smoother experience that you otherwise have to squeeze out of your GPU cluster by optimizing time till first token.
Adding another data point, because this does not seem limited to pure proxy/connect-timeout cases.
Environment:
gpt-5.5, high reasoningHTTP_PROXY/HTTPS_PROXYenv vars in the shell at the time of inspectionObserved behavior:
Reconnecting... 5/5for several minutes, then fell back to HTTP(S).Falling back from WebSockets to HTTP(S) transport: stream disconnected before completion: failed to send websocket request: IO error: Broken pipe (os error 32).time_to_first_token_msaround 295,506 (~4m56s) and full turn duration around 386,761 ms.Why this issue looks like the same root problem:
The user-visible cost is paying the full WebSocket retry budget before an HTTP/SSE path that works. In this case the failure was a send-side broken pipe rather than a plain connect timeout, but the desired behavior is the same: for transport/network-class WebSocket failures, fail over to HTTP/SSE much earlier.
Request:
Please include send-side
Broken pipe/ network write failures in the fast HTTP fallback path, and make the TUI message clearly identify this as a transport fallback rather than making users debug local task execution.I built a small Windows workaround for this: https://github.com/gaopengbin/chatgpt-proxy-launcher
It gives ChatGPT/Codex a process-scoped HTTP proxy without enabling global proxy mode. This fixed the repeated
Reconnecting... 1/5–5/5behavior in my test.For Windows at least, the root cause of this issue is that codex cli for whatever reason (spaghetti code? different lib used for different protocols and they have different default behaviors?) doesn't respect system proxy for its WSS protocol requests but DOES for its HTTPS requests.
But interestingly it (WSS requests) DOES respect environment variables. So, simply
set HTTPS_PROXY=http://localhost:xxxxbefore runningcodexwill immediately fix it.| Connection Type | Respects System Proxy <br>(a.k.a. Internet Options) | Respects System Environment Variables <br>(e.g.,
HTTPS_PROXY) || :--- | :--- | :--- |
| HTTPS Requests | Yes | Yes |
| WSS (WebSocket) Requests | No | Yes |
Adding a macOS Codex Desktop data point and a slightly different feature request.
Environment:
The desired behavior is not necessarily HTTP-only or WebSocket-only. An adaptive transport policy would be more useful:
Reconnecting... 1/5through5/5WebSocket retry budget on every turn when HTTPS/SSE is already known to work.A configurable transport order and a small circuit breaker would preserve WebSocket performance where it is reliable while making unstable proxy networks recover quickly. For example:
The currently exposed feature list in 0.144.4 shows
responses_websocketsandresponses_websockets_v2as removed, so there does not appear to be a supported user-facing way to express this policy today.