Codex 与 AI Coding 实践
解决 Codex `Reconnecting 5/5` 与 `stream disconnected`:从代理配置到固定 HTTPS Streaming
用分层诊断定位代理节点、Streaming 与连接复用导致的 Codex 断联。
本文记录一次特定 Windows、代理与 Codex 配置环境下的实际排查过程。配置项和本地数据结构可能随 Codex 版本变化,修改前请先备份,并以当前版本的官方文档为准。
每次重新启动 Codex,第一次发送消息都要经历 Reconnecting 1/5 到 Reconnecting 5/5,等重试结束后才能正常回答。
我最初以为只是代理没有配置好。补充 .env 后,启动时连续重连的问题确实消失了,但随后又出现了更频繁的对话中断:
stream disconnected before completion: Transport error: network error: error decoding response body
最终,我保留了 .env 中的代理和本机地址绕过配置,同时在 config.toml 中禁用 WebSocket,让 Codex 固定使用 HTTPS Streaming。调整后,连接问题得到大幅改善。
本文记录完整的排查过程,并说明两个容易混淆的问题:
.env到底解决什么?- 为什么配置了代理以后仍然可能断流?
一、最初的现象:每次重启都要 Reconnect 5 次
问题最早出现在 Codex 重启后的第一次对话。
每次重新打开 Codex 并发送消息,客户端都会连续显示:
Reconnecting 1/5
Reconnecting 2/5
...
Reconnecting 5/5
奇怪的是,五次重连结束后,Codex 通常又能继续回答,同一会话中的后续提问也可能恢复正常。
这个现象说明网络并非完全不可用,更像是某种连接方式建立失败,经过多次重试后才切换到另一条可用路径。
结合当时的现象,可以将可能的过程理解为:
新会话发送消息
↓
客户端尝试建立 WebSocket
↓
连接没有成功建立
↓
触发多次 Reconnecting
↓
改用可用的 HTTPS 流式路径
↓
对话恢复
这段流程是根据现象作出的排查推断,并不代表所有版本和网络环境都一定采用相同的回退机制。
二、第一次处理:从没有 .env 到配置代理
检查后发现,本机原本没有 Codex 使用的 .env 文件。因此,这一步不是修改旧配置,而是在下面的位置新建文件:
%USERPROFILE%\.codex\.env
文件内容如下:
HTTP_PROXY=http://127.0.0.1:7897
HTTPS_PROXY=http://127.0.0.1:7897
http_proxy=http://127.0.0.1:7897
https_proxy=http://127.0.0.1:7897
NO_PROXY=localhost,127.0.0.1,::1
no_proxy=localhost,127.0.0.1,::1
其中,7897 是我本机代理软件提供的 HTTP 代理端口,需要根据自己的实际端口修改。
这份 .env 做了什么?
它实际上划分了两类连接:
访问远程服务
↓
通过 127.0.0.1:7897 代理转发
访问 localhost / 127.0.0.1 / ::1
↓
绕过代理,直接连接本机服务
HTTP_PROXY 和 HTTPS_PROXY 指定远程 HTTP/HTTPS 请求使用的代理。大写和小写各写一组,是为了兼容不同程序和网络库读取环境变量时的差异。
真正容易被忽略的是:
NO_PROXY=localhost,127.0.0.1,::1
no_proxy=localhost,127.0.0.1,::1
Codex 启动时不仅需要访问远程服务,也可能需要与本机组件通信。如果访问本机地址的请求也被送进代理,就可能干扰本地连接。NO_PROXY 的作用就是为本机通信划出一条不经过代理的直连路径。
这里还要纠正一个容易产生的误解:
.env不是用来“开启 WebSocket”的。
它配置的是代理路径和绕过规则。WebSocket 是否被采用,是 Codex 传输层的选择;.env 只是让相关网络请求通过正确的路径连接。
完全退出并重新启动 Codex 后,原来每次启动固定出现的 Reconnecting 5/5 消失了。至此,第一层问题看起来已经解决。
三、新的问题:响应还没完成,连接就断了
然而,使用一段时间后,新的错误开始频繁出现:
stream disconnected before completion: Transport error: network error: error decoding response body
这条错误可以分成三层理解:
| 错误片段 | 表示的现象 |
|---|---|
stream disconnected before completion | 流式响应尚未完成,连接已经断开 |
Transport error: network error | 失败发生在网络传输层 |
error decoding response body | 客户端没有获得可供正常继续解析的完整响应数据 |
这里的 error decoding response body 不一定表示服务器返回了格式错误的正文。结合前面的 stream disconnected 和 network error,更合理的理解是:响应体仍在传输过程中,底层连接却已经中断,客户端因此无法继续读取和解析。
与最初的问题相比,故障发生的阶段已经变化:
| 阶段 | 主要表现 | 发生时机 |
|---|---|---|
配置 .env 前 | Reconnecting 1/5 ... 5/5 | 重启后的首次连接 |
配置 .env 后 | stream disconnected before completion | 模型正在流式返回内容时 |
这说明 .env 解决了代理边界和本机通信问题,但不能保证远程长连接在整个响应期间都不会中断。
四、为什么网页能打开,Codex 仍然会断流?
普通网页请求能够成功,并不代表代理链路适合持续传输。
短请求和流式请求对链路的要求并不相同:
短请求:建立连接 → 获取结果 → 很快结束
流式请求:建立连接 → 持续接收数据 → 保持连接 → 响应完成
Codex 的一次回答可能持续较长时间,中间还可能包含推理过程、工具调用及执行结果。如果代理节点发生短暂抖动、连接被中间设备重置,或者线路在任务过程中切换,当前 TCP/TLS 会话就可能失效。
WebSocket 同样依赖长期保持的连接。在我的网络环境中,它虽然不再每次启动都建连失败,却仍然频繁发生传输中断。因此我推测:当前代理链路对 WebSocket 的兼容性或稳定性不足。
这是根据错误现象作出的排查判断,而不是说“WebSocket 在任何网络中都一定比 HTTPS 不稳定”。更准确的结论是:
在我的代理和网络环境下,HTTPS Streaming 的实际稳定性优于 WebSocket。
代理节点本身的稳定性同样会影响结果。排查过程中,我也更换了不稳定的节点,但本文不展开具体代理服务和节点名称。
五、最终处理:禁用 WebSocket,固定使用 HTTPS Streaming
与其等待 WebSocket 失败后再重试或回退,也可以在 Codex 配置中明确禁用 WebSocket。
打开用户级配置文件:
%USERPROFILE%\.codex\config.toml
在保留原有配置的前提下,加入下面的内容:
model_provider = "openai_http"
[model_providers.openai_http]
name = "OpenAI HTTP"
wire_api = "responses"
requires_openai_auth = true
supports_websockets = false
如果文件中已经存在
model_provider,不要重复声明。应修改原来的值,并注意不要破坏已有的 TOML 表结构。修改前最好先备份配置文件。
每一项配置有什么作用?
| 配置项 | 作用 |
|---|---|
model_provider = "openai_http" | 选择下面定义的自定义模型提供方 |
wire_api = "responses" | 继续使用 Responses API |
requires_openai_auth = true | 继续使用 OpenAI 身份认证 |
supports_websockets = false | 告诉 Codex 该提供方不使用 WebSocket 传输 |
最关键的是:
supports_websockets = false
修改后,预期的传输流程变成:
Codex 读取 openai_http 配置
↓
supports_websockets = false
↓
不尝试 Responses WebSocket
↓
直接使用 HTTPS Streaming
↓
持续接收模型响应
这个方案没有关闭 Responses API,也不会把流式回答变成必须等待全部生成完成的普通请求。它改变的是 Responses API 使用的传输方式:由 WebSocket 改为 HTTPS 流式传输。
修改完成后,需要彻底退出 Codex,包括可能仍在运行的托盘进程,然后重新打开,让用户级配置重新加载。
六、切换 HTTPS 后,历史聊天记录为什么不见了?
固定 HTTPS 后,连接稳定性明显改善,但重启 Codex 时,我又遇到了一个新问题:侧边栏中的历史聊天记录不见了。
这个现象很容易让人误以为修改配置删除了会话。实际检查后发现,大多数情况下聊天内容并没有被删除,问题可能来自 model_provider 的变化。
原来的会话记录使用内置 Provider,例如:
model_provider = "openai"
为了禁用 WebSocket,我把它切换成了新定义的 Provider:
model_provider = "openai_http"
Codex 的本地会话状态不只存在于单一文件中,还可能涉及:
~/.codex/sessions
~/.codex/archived_sessions
~/.codex/state_5.sqlite
.codex-global-state.json
切换 Provider 后,这些位置记录的 Provider、会话索引和项目状态可能没有同步更新,于是出现下面的情况:
历史会话文件仍然存在
↓
会话与 SQLite 中的 Provider 元数据不一致
↓
Codex Desktop 无法将它们归入当前 Provider
↓
侧边栏过滤掉这些会话
↓
看起来像历史记录丢失
使用 codex-provider-sync 恢复显示
我参考相关文章,使用了开源工具 codex-provider-sync,把已有会话的相关元数据同步到当前使用的 openai_http Provider。
命令行版本可以通过下面的方式安装:
npm install -g git+https://github.com/Dailin521/codex-provider-sync.git
原文所参考的资料称 CLI 依赖 Node.js 24 或更高版本;较旧版本可能因为
node:sqlite支持问题而无法运行。工具要求可能变化,请以仓库当前说明为准。安装第三方工具前,应自行核对仓库地址、源码、许可证和依赖。
同步前先彻底关闭 Codex、Codex Desktop 和相关 app-server 进程,避免 state_5.sqlite 正在使用而出现:
database locked
然后先检查状态:
codex-provider status
确认当前 Provider 后执行同步:
codex-provider sync --provider openai_http
也可以直接运行:
codex-provider sync
后者不会切换 Provider,只同步当前 Provider 对应的历史会话元数据。完成后重新启动 Codex,原来的历史会话重新出现在侧边栏中。
该工具修复的主要内容包括:
| 同步对象 | 作用 |
|---|---|
sessions | 普通会话文件中的 Provider 元数据 |
archived_sessions | 已归档会话的相关元数据 |
state_5.sqlite | Codex 的本地会话状态和索引 |
| 项目缓存 | 让桌面端重新识别会话与项目的关联 |
它不会重写聊天内容,也不会处理登录状态或重新加密历史消息。根据原文所用版本,同步前会自动在下面的位置生成备份:
~/.codex/backups_state/provider-sync/<timestamp>
如果处理后出现异常,可以使用工具提供的 restore 命令恢复相应备份。
还要注意:恢复列表显示并不保证跨账号或跨 Provider 的旧会话一定能够继续对话。如果历史内容包含与原账号或 Provider 相关的加密数据,仍可能遇到:
invalid_encrypted_content
因此,这个工具解决的是“会话明明存在但桌面端不可见”,而不是所有跨 Provider 会话兼容问题。
七、最终生效的完整配置思路
最终方案不是用 config.toml 替代 .env,而是让两个文件分别解决不同层面的问题。
.env:处理代理路径
HTTP_PROXY=http://127.0.0.1:7897
HTTPS_PROXY=http://127.0.0.1:7897
http_proxy=http://127.0.0.1:7897
https_proxy=http://127.0.0.1:7897
NO_PROXY=localhost,127.0.0.1,::1
no_proxy=localhost,127.0.0.1,::1
它负责:
- 让远程请求经过本机代理;
- 让
localhost等本机地址绕过代理。
config.toml:处理传输方式
model_provider = "openai_http"
[model_providers.openai_http]
name = "OpenAI HTTP"
wire_api = "responses"
requires_openai_auth = true
supports_websockets = false
它负责:
- 保留 Responses API;
- 禁用 WebSocket;
- 固定使用 HTTPS Streaming。
完整排查流程
每次重启都 Reconnecting 5/5
↓
发现没有 Codex .env
↓
配置代理变量和 NO_PROXY
↓
启动时五次重连消失
↓
频繁出现 stream disconnected before completion
↓
判断远程长连接仍不稳定
↓
更换不稳定节点,并禁用 WebSocket
↓
固定使用 HTTPS Streaming
↓
连接问题得到大幅改善
↓
切换 model_provider 后历史会话不可见
↓
使用 codex-provider-sync 同步到 openai_http
↓
历史会话恢复显示
总结
这次问题并不是一个配置就能解释,而是三个阶段连续出现:
- Codex 没有正确区分远程代理流量与本机通信,导致重启后反复出现
Reconnecting 5/5。 - 补充
.env后,WebSocket 路径仍然无法在当前代理环境中稳定维持,导致流式响应中断。 - 禁用 WebSocket 时新增了
openai_httpProvider,原有会话的 Provider 元数据与当前配置不一致,因此历史记录暂时不可见。
最终的解决思路可以概括为:
用 .env 配置正确的代理边界
+
用 config.toml 固定 HTTPS Streaming
+
使用相对稳定的代理节点
+
同步切换 Provider 后的本地会话元数据
↓
Codex 连接稳定性得到改善,历史会话恢复显示
这套方案来自特定环境下的实际排查结果,并不意味着所有 Reconnecting 或断流问题都有相同原因。遇到类似问题时,建议先区分故障发生在首次建连、流式传输期间,还是切换 Provider 之后,再针对对应层次处理。
参考资料
原文提及以下资料,但未提供完整 URL:
- 知乎:Codex 代理与 WebSocket 相关配置
- CSDN:修复 Codex
Reconnecting 5/5 - 腾讯云:Codex 历史会话消失?一键恢复可见
- GitHub:
codex-provider-sync - OpenAI:Codex Configuration Reference
- OpenAI:Responses API Streaming
- OpenAI:Responses API WebSocket Mode