一、表面正常,对话却总是中断
最近使用 Codex CLI 时遇到一个奇怪现象:登录、查看 /status、检查配额都一切正常,但只要发出哪怕最简单的 "hello" 对话,客户端就会立刻报错:stream disconnected before completion: stream closed before response.completed。这个错误字面意思就是“流在完成之前被断开了”,很容易让人第一反应想到网络不稳定。
但反复切换 Wi-Fi、热点、不同网络环境后,问题依旧。仔细观察后发现几个关键细节:请求并非完全发不出去,而是能够建立连接并发出请求,服务端也开始返回内容,只是响应流在中途被关闭。这说明问题不在“能不能连通”,而在于流式返回这一层。
二、真正的线索藏在 /status 和配置文件里
真正让排查方向发生转折的,是 /status 输出中的一行信息:Model provider: custom - https://api.codemirror.codes。这行字很容易被忽略,但它揭示了一个重要事实:当前 Codex CLI 并没有使用默认 provider,而是在走一个自定义的 provider,并且这个 provider 指向了一个具体的 base_url。
于是立刻查看本地配置 ~/.codex/config.toml,果然发现了关键内容:model_provider = "custom",以及 [model_providers.custom] 配置块,其中 base_url 正是 /status 里显示的那个地址。看到这里,基本可以断定,断流问题与这个自定义 provider 密切相关。
这里需要特别澄清一个容易产生的误解:这个自定义配置并不是 Codex CLI 默认生成的,而是用户自己之前配置过的中转站地址,只是后来被遗忘了。也就是说,如果你在配置文件中看到类似的 custom provider,不要怀疑是官方自动写入的,而是应该回忆一下自己是否曾为了其他用途配置过兼容 OpenAI 接口的网关或中转服务。
三、移除配置,问题立刻消失
为了验证推断,最简单的办法就是做一个对照实验:先备份原配置,然后删除 model_provider = "custom" 以及整个 [model_providers.custom] 配置块,只保留基础项。重启 Codex CLI 后,/status 中原来的 custom provider 行消失了,再次发送 "hello" 也能正常返回,之前的 stream disconnected 错误不再出现。
至此可以确认,根因就是本地残留的自定义 provider 配置。这也解释了为什么反复检查网络没有意义——因为网络根本没有问题,是 CLI 在按照旧配置请求一个对流式响应支持不完整的中转服务。
四、通用排查步骤与安全提醒
这次排查过程可以总结为一套通用方法。首先,遇到类似错误时先看 /status 中的 Model provider 行,如果显示 custom,就要立刻检查配置文件。其次,打开 ~/.codex/config.toml,搜索 model_provider、model_providers、base_url、wire_api 等关键词。第三,确认这个 base_url 是否是你自己以前配置过的中转地址,回忆是否复制过别人的配置模板或沿用旧机器的 dotfiles。第四,做一个对照实验:临时移走配置文件再测试,如果恢复正常,说明问题就在原配置里。最后,别忘了检查 shell alias、环境变量和启动参数,避免其他地方又把 provider 指回去。
另外还有一点安全提醒:在向他人求助或贴出配置文件时,一定要对 token、API key 等敏感信息打码。如果发现真实密钥已经泄露,最稳妥的做法是立即撤销并重新生成,不要继续使用旧密钥。这个动作的重要性,完全不亚于修复 CLI 本身。
回顾整个排查过程,最值得记住的并不是某条具体命令,而是一种判断思路:当表面现象与直觉不符时,不要只盯着最显眼的方向,而要根据证据一步步缩小范围。很多技术问题,真正的根因往往藏在那些容易被忽略的细节里。
