跳转到主要内容

Codex 401、429 与 Stream Disconnected:先找出失败的那一层

11 分钟阅读AI

最后一行错误不等于根因。先确认 Codex 走的是 ChatGPT、OpenAI API 还是自定义 provider,再用第一条失败证据选择恢复动作。

Codex 请求依次经过认证、限额、上游和流传输检查点的故障定位图

Codex 可能用不同的最后一行结束一次失败:

text
exceeded retry limit, last status: 429 Too Many Requests stream disconnected before completion exceeded retry limit, last status: 401 Unauthorized

这三行不能互相替换,也不能单独证明根因。401 表示某一条请求路线拒绝了认证;429 表示某个服务施加了请求、余额、支出或用量限制;stream disconnected 只说明响应流没有完整结束。exceeded retry limit 则是客户端多次尝试后停止的结果,不是另一种账户额度。

最省时间的处理方式,是先确定请求真正走到哪里,再找第一条失败证据。不要一开始就删除认证文件、换 key、提高 timeout 或连续重跑同一个大任务。

先做三项只读检查

在修改任何状态前,记录错误原文、失败时间和时区、Codex 版本、使用的客户端、模型名称,以及界面中可见的 request ID。CLI 用户可以先运行:

bash
codex --version codex login status

第一条固定客户端版本;第二条只确认当前认证方式。不要把输出中的账户标识、token 或 key 放进公开 issue。若使用自定义 provider,再检查当前生效的 model_provideropenai_base_urlmodel_providers.<id>,但不要粘贴包含凭据的完整配置。

接着把失败阶段分清:

  • 启动或发送前就出现 401,更接近认证或 route 配置;
  • 请求已发出并收到明确 429,需要读取该响应的 codemessage 和响应头;
  • 已经输出部分内容后才断开,更接近 response stream、代理、网关或短暂服务异常;
  • 只看到最终 retry-limit 行,说明还缺少更早的失败证据。

官方 Codex App Server 文档把 Unauthorized、上游 4xx/5xx、ResponseStreamConnectionFailedResponseStreamDisconnectedResponseTooManyFailedAttempts 列为不同错误类别;如果上游 HTTP 状态可用,还会单独携带 httpStatusCode。这正是为什么“都显示 retry limit”不能视为同一种故障。查看官方错误分类

先确认是哪条账户与 provider 路线

同一个 Codex 界面可能使用完全不同的计费、认证和限额 owner。

当前路线应查看的证据常见误判
ChatGPT 登录的 Codexcodex login status、账户内 Codex 用量、同账户的新会话复现用 Platform API 余额解释 ChatGPT 使用窗口
OpenAI API keyAPI 错误 payload、组织/项目、账单与限制、响应头用 ChatGPT Plus/Pro 状态证明 API 一定可用
自定义 provider 或网关生效的 provider/base URL、网关日志、上游 request ID、该服务的账户状态默认所有 401/429 都是 OpenAI 返回

如果你查看的是错误账户或错误平台,即使页面显示“还有额度”,也没有诊断价值。先让认证方式、目标 provider 和你查看的控制台属于同一条路线。

401:先证明谁拒绝了哪种凭据

OpenAI Platform API 的官方错误文档把 401 分成多种情况:无效认证、错误 API key、缺少组织成员资格,以及 IP allowlist 不匹配。具体动作由错误 payload 和当前项目决定,而不是一律“重新登录”。对照 OpenAI API 401 分类

ChatGPT 登录路线

先看 codex login status 是否与预期账户和认证方式一致。如果账户明显不对、登录已失效,才考虑使用官方登录流程重新认证。codex logout 会清除已保存的本地凭据,是会改变状态的操作;在未记录当前方式、未确认没有受管身份或工作区约束前,不应把它当作第一步。官方认证说明也区分了已保存认证与 workload identity。

重新认证后的成功标准,不是“登录页打开了”,而是原账户、原 provider 上的一个短请求能够完成。如果只能换账户后成功,应记录为绕过了原路线,不能宣布原问题已修复。

API key 路线

核对实际进程使用的 key 对应哪个组织和项目,不要在 shell history 或 issue 中打印 key。若错误明确是 invalid_api_key、organization membership 或 IP allowlist,就修正该条件后再发送一次短请求。稳定的 401 不应退避重试;凭据或权限状态没有改变,重复发送不会变成成功。

自定义 provider 路线

401 可能由网关自己返回,也可能是网关转发了上游拒绝。用网关 request ID 对齐同一时刻的日志,确认失败发生在客户端到网关、网关认证,还是最终模型服务。不要拿一个 provider 的 key 去测试另一个 base URL。

429:读取具体 owner,再决定是否等待

OpenAI Platform API 的 429 不只有“请求太快”。当前官方分类还包括 credit balance exhausted、组织或项目 spend limit、组织 usage limit。官方 API error 文档明确指出,余额、支出或 quota 类错误不会因为持续重试而恢复。

根据可观察信号选择动作:

看到的证据下一步停止条件
Retry-After 或明确的 request-rate 信息降低并发,至少等待响应要求的时间,再做有限重试达到最大尝试次数或总等待上限
credit_balance_exhausted检查当前组织的余额与账单余额状态未变化前不重试
organization/project spend limit核对实际请求所属的组织和项目限制管理员状态未变化前不重试
usage limit 或 ChatGPT 账户窗口按当前账户界面给出的恢复条件处理窗口未恢复前不连续发送
第三方 provider 的 429查该 provider 的限制、账单、并发与日志不拿 OpenAI 控制台替代第三方证据
只有 Codex 最后一行 429保存时间、request ID 和 route,补更具体证据证据不足时不猜固定等待时间

若单个短请求稳定成功,而并发任务失败,可以先降低并发并记录阈值。这是对请求形态的证据,不等于已经证明根因。若降低并发后仍无规律失败,停止试探,回到真实 provider 和网关日志。

Stream disconnected:先判断响应走到哪一步

stream disconnected before completion 与 HTTP 401/429 可以相邻出现,但不是同一含义。它可能发生在客户端、代理/TLS 检查、公司网络、网关、上游服务或本地睡眠/切网造成的长连接中断。错误文本本身不能决定是哪一个。

做一次小范围对照即可:

  1. 用同一账户、同一 provider 和同一短请求新建会话;
  2. 记录是完全没有输出、输出一部分后中断,还是返回明确 HTTP 状态;
  3. 如果组织策略允许,在不上传敏感内容的前提下,用另一条可信网络做一次相同测试;
  4. 对齐失败时间与 provider/网关日志;
  5. 如果只在一个客户端或版本复现,记录版本差异后停止反复切换变量。

用只读基线、短请求、响应形态和有限对照定位 Codex 401、429、流中断与重试耗尽的最小测试图

另一网络成功只能说明网络路径值得继续查,不证明必须关闭 VPN、防火墙或证书检查。受管设备上的安全策略不应为了排障被绕过。两条网络都在同一时刻、同一 provider 失败,则更应查看上游状态、账户与 request ID。

如果错误发生在输出一部分之后,先检查是否能安全续接或重新发起一个更小任务;不要默认扩大 stream_idle_timeout_ms。timeout 只改变客户端等待多久,无法修复稳定的 401、错误 base URL、耗尽的余额或被网关主动关闭的连接。

为什么提高重试次数通常不是第一步

Codex 的 provider 配置确实包含 HTTP request retries、stream retries 和 stream idle timeout。当前官方配置参考同时说明,provider、auth 与 model_providers 属于用户级配置,项目内 .codex/config.toml 不能覆盖这些机器级路线。

这些设置控制“失败后客户端如何等待和再试”,不控制账户余额、权限、上游策略或网络设备。提高次数可能产生三种副作用:延长一个确定失败;在多层网关中放大请求;把第一条有用错误埋在更多 retry 日志后。

只有在已经确认是短暂传输失败或 rate limit、上游允许重试、且有明确总时间边界时,才考虑调整。修改后仍应以一个短请求验证;若原始错误稳定重现,就恢复到最小配置并处理真正 owner。

一份可以直接用于升级处理的证据包

当问题跨新会话持续、账户页面与错误矛盾、同一最小请求稳定失败,或只有特定版本/provider 组合失败时,停止猜测,整理:

从账户与 provider 路线、401 和 429 owner、stream 对照到脱敏升级材料的 Codex 故障证据清单

  • Codex 版本、CLI/App/IDE、操作系统;
  • 认证方式与 provider 名称,base URL 只保留主机和必要路径;
  • 首次与最近失败时间及时区;
  • 失败发生在发送前、首字节前还是部分输出后;
  • 完整错误类型、HTTP 状态、错误 code 和 request ID;
  • 单会话/全会话、单模型/多模型、串行/并发的复现范围;
  • 已做过的一次对照测试及其结果;
  • 脱敏后的最小日志片段。

不要附 API key、token、完整认证文件、未脱敏环境变量或业务源码。证据包的目标是让支持人员能把 request ID、时间和 provider 对上,不是上传整台机器的状态。

最后的恢复验收也要回到原路线:原账户、原 provider、原客户端上的一个短请求能够完整结束,而且第一条失败证据不再出现。换网络、换模型或换账户后成功,只说明找到临时绕行;原路径是否恢复,仍需单独验证。

#Codex#401 Unauthorized#429 Too Many Requests#Stream Disconnected
分享文章: