Codex CLI 接自定义 API 后,报错大多集中在凭证、路径、模型、限流、上下文和本地沙箱六层。看到红色提示就换模型、重装工具,往往把十分钟的问题拖成半天。更有效的做法是固定变量:同一个 Key、Base URL 和模型 ID,一次只改一项。本文按状态码拆解,并给出日志位置、诊断命令和错误处理示例。
说明:OpenAI、Codex 是 OpenAI, Inc. 的商标。本文仅作技术说明,与上述公司无隶属或合作关系。配置与文案随版本调整,以官方文档和当前版本为准;模型与价格以站内模型价格页为准。
一、先看状态码,再动配置
| 现象 | 常见含义 | 先查什么 | 是否重试 |
|---|---|---|---|
401 |
Key 缺失、错误或失效 | env_key 变量、Key 状态、余额 |
不重试 |
403 |
Key 无权限或策略拦截 | 模型权限、账户状态、团队策略 | 不重试 |
404 |
路径错误或接口不存在 | Base URL、/responses 支持情况 |
不重试 |
model not found |
模型 ID 错误或未开通 | 模型标识、账号权限 | 不重试 |
429 |
频率、并发或配额超限 | 用量、共享 Key、重试设置 | 退避后重试 |
400 context_length_exceeded |
上下文超过模型上限 | 输入体积、工具输出、压缩设置 | 改请求后重试 |
| 沙箱或审批失败 | 本地权限边界拦截 | 沙箱模式、可写目录、审批策略 | 调整策略后重试 |
| 超时或流中断 | 代理、TLS、空闲超时、服务端过载 | 网络链路、超时与重试参数 | 视情况重试 |
建议按下面的顺序排查:
- 在项目目录执行
codex doctor,先看安装、配置、认证和运行环境。 - 会话内用
/status看模型、审批策略、可写目录和 Token 用量。 - 用
/debug-config看最终生效值,确认改的不是没被加载的文件。 - 用最小请求验证 Base URL、Key 和模型。
- 最后再调整模型、上下文或沙箱策略。
二、401 与 403:Key 没有进到进程里
Codex 的自定义 provider 通过 env_key 指定环境变量名,例如:
[model_providers.zsqh]
name = "ZSQH AI Gateway"
base_url = "https://ai.zhongshangqihang.com/v1"
env_key = "ZSQH_API_KEY"
wire_api = "responses"
配置写对,不等于进程能读到 Key。常见原因:shell 里导出的变量名和 env_key 不一致;在 A 终端导出,却在 B 终端启动;图形界面启动的应用没继承环境变量;Key 前后带空格、换行或引号;Key 属于另一个平台或环境;Key 已删除、禁用或余额不足。
无头环境可以用 CODEX_API_KEY 传入 Key,但不要同时保留多套来源,否则很难判断最终用的是哪一把。403 更多是权限或策略问题,先看响应体,再查网关控制台,不要反复重试。
三、404 与 model not found:地址、协议和模型 ID
Codex 当前的自定义 provider 只接受 wire_api = "responses",请求会打到 /v1/responses。这带来几类高频 404:
base_url少写/v1,请求打到网页路由。base_url已包含/responses,客户端又拼一次,路径重复。- 网关只提供
/v1/chat/completions,没有实现 Responses 协议。 - 域名拼错,或把控制台地址当成了 API 地址。
base_url 一般填到 /v1 为止,不要自己拼完整接口路径。模型不存在时,不同网关可能返回 404,也可能返回 400,错误码字段常见为 model_not_found,判断以响应体为主。模型 ID 必须和站内模型价格页的 API 标识完全一致,包括大小写、连字符和版本后缀。
codex debug models 导出的是本地或内置目录,不代表网关实际开放了哪些模型。还要确认 model_provider 与 [model_providers.xxx] 名称一致;对不上时,Codex 可能回落到默认 provider,表现就像“配置没生效”。
四、429:先降并发,再谈重试
429 表示请求超过了速率、并发或 Token 配额。Codex 会连续读文件、跑命令,比普通聊天更容易触发。常见场景:每分钟请求数或 Token 数超限;多人共用一把 Key;在大仓库里连续读取大量文件;重试没有退避,形成风暴;长上下文请求挤占并发空间。
Codex 的 provider 配置里有 request_max_retries(默认 4)和 stream_max_retries(默认 5)。它们能提高稳定性,但在持续 429 时会放大请求量,排查阶段可以临时调低。
还要区分限流和欠费:错误体出现 insufficient_quota 一类字段时,重试没有意义,应去控制台检查余额或配额。真正的限流则看 Retry-After,没有该响应头就做指数退避加随机抖动。按项目或按人拆 Key,比全组共用一把更容易定位。
五、上下文超限:先减输入,再谈换模型
上下文超限常见错误码是 context_length_exceeded,文案里可能出现 “maximum context length”。Codex 的请求不只有你的提问,还包括系统提示、AGENTS.md、读入的文件、工具输出和历史记录。长任务跑久了,前面每一步的输出都会留在上下文里。
处理顺序建议如下:
- 缩小工作目录,只让 Codex 读相关模块。
- 在提示里限定文件范围,避免整仓库扫描。
- 排除构建产物、依赖目录、日志和密钥文件。
- 用
tool_output_token_limit限制单个工具输出的 Token 数。 - 新开会话,把已完成的结论写成简短摘要再继续。
- 确有必要时,再换上下文更长的模型。
model_context_window 要和真实窗口一致,填大数字仍会被服务端拒绝;model_auto_compact_token_limit 设得过高可能先撞上硬上限。实际窗口以官方文档和价格页为准。
六、沙箱与审批失败:这不是 API 错误
Codex 有三档沙箱模式:read-only、workspace-write 和 danger-full-access。read-only 不能改文件;workspace-write 只能在可写根目录内修改,并可配置网络访问;danger-full-access 移除文件和网络边界,只适合受控环境。
典型表现是 Operation not permitted、Permission denied,或者命令执行到一半提示需要审批。先看 /status 显示的模式和可写目录,再确认项目是否在目录之外、命令是否需要网络、非交互的 codex exec 是否有审批入口。
审批策略方面,当前版本支持 on-request、never 和 granular。旧的 approval_policy = "untrusted" 已不再支持,继续保留可能导致 Codex 无法启动;on-failure 也已弃用。CI 里可以明确写 codex exec --sandbox workspace-write;只读任务可用 --sandbox read-only --ask-for-approval never。不要为了省事直接上 danger-full-access。
七、超时与流中断:代理、TLS 和空闲超时
流式请求对网络链路更敏感。公司代理、TLS 中间人、VPN 切换和不稳定的出口,都可能表现为“请求发出去了,但迟迟没有第一个 Token”,或者中途断流。
stream_idle_timeout_ms 默认 300000 毫秒(五分钟)。推理模型首 Token 较慢,调得过低会误伤;如果代理 60 秒断空闲连接,调大客户端超时也救不回来,需要同时查链路。
自签 CA 或 TLS 拦截可用 CODEX_CA_CERTIFICATE 指定 PEM 证书包,未设置时才回退 SSL_CERT_FILE;不要整体关闭证书校验。超时后先发一次非流式最小请求,确认 API 可用,再回 Codex 复现。
八、日志与诊断:先拿证据,再改配置
Codex 的日志目录由 log_dir 控制,默认是 $CODEX_HOME/log。只有显式设置 log_dir 时,才会额外生成明文 codex-tui.log,排查时建议在用户级配置里打开。
常用诊断入口:
codex doctor:输出安装、配置、认证、运行时和终端健康报告。/status:会话内查看模型、审批策略、可写目录和 Token 用量。/debug-config:查看配置来源、优先级和最终生效值。codex exec --json:以 JSON 事件流输出非交互执行过程。RUST_LOG:控制日志详细程度,例如codex_core=debug,codex_tui=debug;codex exec默认只显示 error 级别。
排查时对齐配置最终值与实际请求:Base URL、/responses 路径、模型名、审批策略。很多“配置不生效”是文件位置不对或环境变量未重载。
九、一段可复用的错误处理示例
下面的示例用于你自己调用网关的脚本,不替代 Codex CLI 内置的重试。原则是:认证和路径错误不重试,限流和 5xx 退避重试,上下文错误直接改请求。
import random
import time
import httpx
RETRYABLE = {429, 500, 502, 503, 504}
def call_gateway(payload: dict, key: str, url: str):
for attempt in range(4):
try:
resp = httpx.post(
url,
json=payload,
headers={"Authorization": f"Bearer {key}"},
timeout=httpx.Timeout(180.0, connect=10.0),
)
except httpx.TimeoutException:
if attempt == 3:
raise
time.sleep(min(30, 2 ** attempt) + random.random())
continue
# 认证、权限、路径、模型错误:改配置,不要重试
if resp.status_code in (401, 403, 404):
raise RuntimeError(f"{resp.status_code}: {resp.text[:300]}")
if resp.status_code == 400:
body = resp.text.lower()
if "context" in body or "maximum context" in body:
raise RuntimeError("上下文超限:先缩小输入或新开会话")
raise RuntimeError(f"请求格式错误: {resp.text[:300]}")
if resp.status_code in RETRYABLE:
if "insufficient_quota" in resp.text:
raise RuntimeError("配额不足:检查余额,不要重试")
retry_after = float(resp.headers.get("Retry-After", 2 ** attempt))
time.sleep(min(30, retry_after) + random.random())
continue
resp.raise_for_status()
return resp.json()
raise RuntimeError("重试次数已用完")
这段代码不处理沙箱和审批,那属于本地执行层。把 API 错误和本地权限错误分开看,排查会快很多。
常见问题
Key 在网页测试正常,Codex 却报 401?
先确认 Codex 读取的环境变量名,并在启动 Codex 的同一个 shell 里导出。图形界面启动的应用经常读不到刚设置的变量,重开应用或用 codex doctor 检查认证。
404 一定是模型下线了吗?
不一定。Codex 使用 Responses 协议,路径不对、网关没有 /v1/responses 入口都会返回 404。先确认地址填到 /v1,再核对模型 ID。
429 要不要把重试次数调大?
不建议。持续 429 说明已经超过限额,调大重试只会增加请求量。先降并发、拆 Key、看 Retry-After,确认是限流还是欠费。
Codex 能用 Chat Completions 接口吗?
当前只接受 wire_api = "responses"。只有 Chat Completions 的端点需要协议转换层,或改用其他客户端;不要靠安装旧版本绕过。
沙箱报错能不能直接关掉?
可以调整为 workspace-write 并配置可写目录,或在受控环境使用更高权限模式,但不建议默认使用 danger-full-access。先看 /status 确认边界。
下一步
Codex 的报错排查,顺序比技巧重要:先看状态码和响应体,再用 codex doctor 与 /debug-config 确认配置,最后才改模型或沙箱。需要统一 Key、用量和模型入口,可以注册中商起航 AI 网关,模型与接口范围以模型价格页为准。
相关阅读:
