Codex 可能用不同的最后一行结束一次失败:
textexceeded 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 用户可以先运行:
bashcodex --version codex login status
第一条固定客户端版本;第二条只确认当前认证方式。不要把输出中的账户标识、token 或 key 放进公开 issue。若使用自定义 provider,再检查当前生效的 model_provider、openai_base_url 或 model_providers.<id>,但不要粘贴包含凭据的完整配置。
接着把失败阶段分清:
- 启动或发送前就出现 401,更接近认证或 route 配置;
- 请求已发出并收到明确 429,需要读取该响应的
code、message和响应头; - 已经输出部分内容后才断开,更接近 response stream、代理、网关或短暂服务异常;
- 只看到最终 retry-limit 行,说明还缺少更早的失败证据。
官方 Codex App Server 文档把 Unauthorized、上游 4xx/5xx、ResponseStreamConnectionFailed、ResponseStreamDisconnected 和 ResponseTooManyFailedAttempts 列为不同错误类别;如果上游 HTTP 状态可用,还会单独携带 httpStatusCode。这正是为什么“都显示 retry limit”不能视为同一种故障。查看官方错误分类。
先确认是哪条账户与 provider 路线
同一个 Codex 界面可能使用完全不同的计费、认证和限额 owner。
| 当前路线 | 应查看的证据 | 常见误判 |
|---|---|---|
| ChatGPT 登录的 Codex | codex login status、账户内 Codex 用量、同账户的新会话复现 | 用 Platform API 余额解释 ChatGPT 使用窗口 |
| OpenAI API key | API 错误 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 检查、公司网络、网关、上游服务或本地睡眠/切网造成的长连接中断。错误文本本身不能决定是哪一个。
做一次小范围对照即可:
- 用同一账户、同一 provider 和同一短请求新建会话;
- 记录是完全没有输出、输出一部分后中断,还是返回明确 HTTP 状态;
- 如果组织策略允许,在不上传敏感内容的前提下,用另一条可信网络做一次相同测试;
- 对齐失败时间与 provider/网关日志;
- 如果只在一个客户端或版本复现,记录版本差异后停止反复切换变量。

另一网络成功只能说明网络路径值得继续查,不证明必须关闭 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 组合失败时,停止猜测,整理:

- Codex 版本、CLI/App/IDE、操作系统;
- 认证方式与 provider 名称,base URL 只保留主机和必要路径;
- 首次与最近失败时间及时区;
- 失败发生在发送前、首字节前还是部分输出后;
- 完整错误类型、HTTP 状态、错误
code和 request ID; - 单会话/全会话、单模型/多模型、串行/并发的复现范围;
- 已做过的一次对照测试及其结果;
- 脱敏后的最小日志片段。
不要附 API key、token、完整认证文件、未脱敏环境变量或业务源码。证据包的目标是让支持人员能把 request ID、时间和 provider 对上,不是上传整台机器的状态。
最后的恢复验收也要回到原路线:原账户、原 provider、原客户端上的一个短请求能够完整结束,而且第一条失败证据不再出现。换网络、换模型或换账户后成功,只说明找到临时绕行;原路径是否恢复,仍需单独验证。



