Codex 每次对话都要重连五次
最近用 Codex 桌面端,每次发消息都要先等它重连。从 1/5 数到 5/5,然后才开始正常回答。偶尔一次还能接受,每轮对话都来一遍就很烦了。尤其只是想补一句话,也得陪它重新走完这个流程。
我先在网上搜了一圈,找到的解释是:WebSocket 连接失败,重试五次后回退到 HTTP,所以最后还是能收到回答。但搜到的解决办法大多是让 Codex 直接使用 HTTP,跳过前面这五次重试。
我想用的还是原生 WebSocket,于是决定顺着这个线索,看看连接到底卡在了哪里。
最先怀疑的当然是代理。我的网络由 v2rayN 管理,之前就有过不太稳定的情况;OpenVPN 倒是稳定,但速度又慢。可这次连 TUN 开着也会重连,光说“把 TUN 打开”显然没有解决问题。
于是我让 Codex 直接检查本机配置和日志。这篇就是当天的排查记录,中间还真走了一点弯路。
一开始查错了连接
Codex 自己也需要分清楚自己在连什么。
前半段排查找到的是本地执行器连接云端的 rendezvous 通道。调整配置、重启对应进程后,日志里出现了连接成功,Codex 当时就判断问题已经恢复。但这条连接负责的是执行器通信。我们要解决的是模型对话开始时那五次重连,两者还不是一回事。
我补了一句:“但是 TUN 模式开启的情况下也会出现重连五次。”这才把排查重新拉回当前对话。后面直接按会话编号查日志,终于找到了和 1/5~5/5 对应的失败请求。
它连接的是这个地址:
wss://chatgpt.com/backend-api/codex/responses日志里的错误先是 request timed out,接着反复出现 Windows 的 10061:
由于目标计算机积极拒绝,无法连接。 (os error 10061)重试次数、发生时间、请求地址都对上了。接下来就围着这条连接查,不再拿其他服务的连通情况代替它。
同一个接口,换条路试
当时 v2rayN 的本地代理入口是 127.0.0.1:10808。我们对上面的模型接口做了两次 WebSocket 握手测试,一次直连,一次明确经过这个代理入口。这组对比测试时,TUN 是关闭的。
直连在 TCP 阶段等了约 12 秒,最后超时。经过代理的请求则在约 1.3 秒后拿到了:
HTTP/1.1 101 Switching ProtocolsTLS 证书校验正常,WebSocket 握手响应也校验通过。测试只建立连接,没有发送模型生成请求。
这个结果就很有用了:当前节点能连上 Codex 的 WebSocket 接口。至少不用马上去找另一台服务器,应该先看看 Codex 自己有没有用上这条已经测通的路径。
顺便也纠正了我对本机环境的一个印象。一直习惯把这套配置叫作“v2rayN 管理的 sing-box”,但当时关着 TUN,实际运行的代理核心是 Xray。后来开启 TUN,才又看到了 sing-box 进程和 singbox_tun 网卡。查配置还是得看当时运行的东西。
文件改了,会话还在用旧配置
前面调整配置时,我们已经在 Codex 的配置文件里加了一个开关。
Windows 下的文件位置是:
%USERPROFILE%\.codex\config.toml在已有的 [features] 段中加入这一行,没有这个段再新建:
[features]
respect_system_proxy = true这项设置用于让 Codex 遵循系统代理配置。排查时桌面端内置的 CLI 版本是 0.162.0-alpha.17.2,功能列表里已经能找到它,状态标记为 under development。
保存后再检查,文件里明明是 true,当前会话的运行日志却还是:
feature.respect_system_proxy = false重新启动一个命令行进程读取配置,得到的又是 true。也就是说,文件已经改对了,正在处理这段对话的进程还没有用上新值。
我前面确实重启过服务,但重启的是代理服务。v2rayN 重新运行,不会顺带让 Codex 重新读取自己的配置。
于是这次完整退出 Codex,再重新打开。不是只关掉对话,也不是再重启一次代理核心。
回到 TUN 模式再发一条消息
重启后,我开启 TUN,回到原来的对话里发了一条测试消息:
已重启。test 本对话 TUN 模式会不会 5 次重连。
这次没有再看到那串重连提示,消息直接开始处理。日志也跟上了这个变化。当前会话里的 respect_system_proxy 已经是 true,singbox_tun 网卡状态为 Up。这次复测时,Windows 系统代理是关闭的,网络由 TUN 接管。
之后,Codex 进程的日志里出现了这一行:
successfully connected to websocket: wss://chatgpt.com/backend-api/codex/responses这次连上的就是前面报错的模型接口。本轮会话里也没有查到那组五次重试记录。
这里还有个查日志时的小插曲:最初只按会话编号筛选,没有找到连接成功的记录。继续检查同一 Codex 进程中没有挂会话编号的网络日志,才找到了上面这行。后面再排查这类问题,除了会话编号,还得把进程和时间段一起对上。
留下这套能用的配置
最后我保留了 respect_system_proxy = true,在 TUN 开启、系统代理关闭的状态下完成了复测。配置加载了,模型 WebSocket 连上了,对话前的五次重连也消失了。至于 MTU、DNS 和节点,这一轮就没有继续改下去。
回头看,前面有两处很容易让人白忙:一处是看见某条连接恢复,就以为整个 Codex 都恢复了;另一处是配置文件已经改好,却一直拿还没加载新配置的会话测试。
以后再碰到这五次重连,我会先翻出真正失败的地址,再看运行进程里的配置。这次总算可以发完消息就等回答,不用先陪它数到五了。
