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

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

- URL: https://blog.laozhang.ai/zh/posts/codex-exceeded-retry-limit-429
- Published: 2026-08-22
- Updated: 2026-09-01
- Author: LaoZhang AI Team (https://blog.laozhang.ai/zh/about)
- Topic: ChatGPT 与 OpenAI
- Tags: Codex, 401 Unauthorized, 429 Too Many Requests, Stream Disconnected

---
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_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”不能视为同一种故障。[查看官方错误分类](https://learn.chatgpt.com/docs/app-server#errors)。

## 先确认是哪条账户与 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 分类](https://developers.openai.com/api/docs/guides/error-codes#api-errors)。

### ChatGPT 登录路线

先看 `codex login status` 是否与预期账户和认证方式一致。如果账户明显不对、登录已失效，才考虑使用官方登录流程重新认证。`codex logout` 会清除已保存的本地凭据，是会改变状态的操作；在未记录当前方式、未确认没有受管身份或工作区约束前，不应把它当作第一步。[官方认证说明](https://learn.chatgpt.com/docs/auth#check-authentication-or-sign-out)也区分了已保存认证与 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 文档](https://developers.openai.com/api/docs/guides/error-codes#api-errors)明确指出，余额、支出或 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、流中断与重试耗尽的最小测试图](https://blog.laozhang.ai/posts/zh/codex-exceeded-retry-limit-429/img/minimal-comparison-test.webp)

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

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

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

Codex 的 provider 配置确实包含 HTTP request retries、stream retries 和 stream idle timeout。当前[官方配置参考](https://learn.chatgpt.com/docs/config-file/config-reference#configtoml)同时说明，provider、auth 与 `model_providers` 属于用户级配置，项目内 `.codex/config.toml` 不能覆盖这些机器级路线。

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

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

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

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

![从账户与 provider 路线、401 和 429 owner、stream 对照到脱敏升级材料的 Codex 故障证据清单](https://blog.laozhang.ai/posts/zh/codex-exceeded-retry-limit-429/img/support-evidence-checklist.webp)

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

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

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

## 参考来源

本文引用的外部页面，按正文出现顺序排列。最后更新于 2026-09-01。

- [查看官方错误分类](https://learn.chatgpt.com/docs/app-server) (learn.chatgpt.com)
- [对照 OpenAI API 401 分类](https://developers.openai.com/api/docs/guides/error-codes) (developers.openai.com)
- [官方认证说明](https://learn.chatgpt.com/docs/auth) (learn.chatgpt.com)
- [官方配置参考](https://learn.chatgpt.com/docs/config-file/config-reference) (learn.chatgpt.com)
