Back to writing

Blog

Fixing Codex Stuck on Reconnecting

CodexmacOSNetwork Proxy

Recently, while using the Codex desktop app on macOS, I kept seeing "Reconnecting" for long stretches. Regular websites and other networked apps were mostly fine, but Codex would retry five times whenever I first started using it. This post records how I resolved that particular issue.

The visible symptoms in Codex were:

  • "Reconnecting" appeared frequently.
  • The app retried automatically after a wait of a dozen seconds or so.
  • WebSocket connections timed out.

Codex's streaming responses primarily rely on WebSocket. Being able to open a regular webpage does not necessarily mean that a long-lived WebSocket connection is working too.

Local environment

I use Clash Verge, with Mihomo as the underlying proxy core.

I checked the listening TCP ports with:

lsof -nP -iTCP -sTCP:LISTEN

The result showed Mihomo listening on:

*:7897

Checking Clash Verge's running configuration confirmed:

mixed-port: 7897

In other words, 7897 is a mixed port that supports both HTTP and SOCKS5 proxies.

For your own setup, use the port that is actually listening and the final runtime configuration generated by Clash.

Locating the problem

I checked the macOS system proxy settings:

scutil --proxy

At the time, the system did not provide a valid proxy configuration that Codex could use directly.

Next, I checked the proxy environment variables in the current process:

env | grep -i proxy

There were no HTTP_PROXY, HTTPS_PROXY or ALL_PROXY variables.

Although Clash was running and TUN mode might already have been handling some traffic, Codex itself did not know about the local proxy. Transparent routing can sometimes work for ordinary HTTPS requests, but the network path may be less reliable for long-lived WebSocket connections.

Confirming the failure in the Codex logs

The Codex log database is located at:

~/.codex/logs_2.sqlite

The logs contained many errors like these:

stream disconnected - retrying sampling request
sampling_error=request timed out
Connection reset by peer
invalid peer certificate

Some requests were retried five times in a row. This showed that "Reconnecting" was not merely a display issue: streaming connections were actually being interrupted.

Clash Verge's logs also showed that traffic for chatgpt.com and ws.chatgpt.com was going through the proxy, but connections through the current node had been canceled. That suggested two possible layers to the problem.

First, Codex had no explicit proxy environment variables and could only rely on the system proxy or TUN routing.

Second, the current Clash node was not particularly reliable for long-lived connections.

Checking with Codex Doctor

The newer version of Codex includes a diagnostic command:

codex doctor --json

If the codex command on your system is not the version bundled with the desktop app, you can also use the executable inside the app:

/Applications/ChatGPT.app/Contents/Resources/codex doctor --json

Before the fix, the diagnostics showed:

proxy env vars: none
Responses WebSocket timed out
handshake timed out
connect timeout: 15000 ms

Meanwhile, the regular ChatGPT HTTPS endpoint was still reachable. This further narrowed the issue to long-lived WebSocket connections, rather than a complete loss of network access.

The fix

I created the following file in Codex's default state directory:

~/.codex/.env

I added these settings:

HTTP_PROXY=http://127.0.0.1:7897
HTTPS_PROXY=http://127.0.0.1:7897
ALL_PROXY=socks5h://127.0.0.1:7897
NO_PROXY=localhost,127.0.0.1,::1

Here is what each setting does:

HTTP_PROXY handles ordinary HTTP requests.

HTTPS_PROXY sends HTTPS requests through the local HTTP CONNECT proxy. Using http://127.0.0.1:7897 here is intentional: it describes how the client connects to the local proxy, not whether the destination website uses HTTP.

ALL_PROXY uses socks5h as a fallback for other protocols and connection methods. The h means that hostname resolution is also delegated to the proxy.

NO_PROXY excludes local loopback addresses so that Codex's local services, plugins and internal processes are not sent through the proxy too.

After creating the file, its permissions can be restricted:

chmod 600 ~/.codex/.env

This allows only the current user to read or write the file.

Results

After saving .env, I reran the diagnostics without passing proxy variables temporarily on the command line:

codex doctor --json

Codex automatically read ~/.codex/.env, and the results changed to:

proxy env vars present:
HTTP_PROXY, HTTPS_PROXY, ALL_PROXY, NO_PROXY

Responses WebSocket handshake succeeded
HTTP 101 Switching Protocols

The WebSocket handshake took about 1.4 seconds. Before the fix, it would wait 15 seconds and then time out.

HTTP 101 Switching Protocols is the standard response for a successful WebSocket handshake, showing that Codex could now establish a streaming connection through the local proxy.

Summary

The core issue was that ordinary HTTPS requests worked, while the Responses WebSocket connection could not be established reliably.

My approach was to first check the actual proxy port, which in my Clash Verge setup was the 7897 mixed port. I then used the Codex logs and codex doctor to confirm the WebSocket handshake timeout. Finally, I explicitly configured the HTTP, HTTPS and SOCKS5 proxies in ~/.codex/.env.

P.S.

If you would rather not work through all of this yourself, you can send GPT the following request:

"Please help me fix Codex repeatedly showing Reconnecting. Check my local proxy port, then create or update the ~/.codex/.env file with the correct proxy settings. Feel free to ask if you run into a problem or need me to step in."

Oh, magical mambo~