Skip to content

让 Codex 尽可能重试:stream_max_retries 与无限重连配置

让 Codex 尽可能重试:stream_max_retries 与无限重连配置

最近把 Codex 的 stream_max_retries 调到 10 后,我发现界面经常停在:

1
Reconnecting... 10/10

看起来像是第 10 次重试后卡死了。翻了当前 Codex 源码后,发现这里有两个容易误解的机制。

本文基于 2026-08-19 的 openai/codex main 分支(commit f5a3dc5)记录,后续实现可能变化。

1. stream_max_retries 不限制所有重试

stream_max_retries 默认是 5,配置硬上限是 100。它控制的是普通 streaming response 断开后的重连次数。

但 Codex 现在还有一个默认开启的 feature:

1
2
[features]
unbounded_connection_retries = true

当错误被分类为 ConnectionFailed 时,sampling 请求会绕过 stream_max_retries,进入另一套无限重试逻辑:

1
5s -> 10s -> 20s -> 40s -> 60s -> 60s -> 60s -> ...

也就是说,stream_max_retries = 10 并不意味着“整个请求最多重试 10 次”。

相关源码:

2. 10/10 本身也可能要等很久

普通 stream retry 使用的退避大致是:

1
200ms * 2^(attempt - 1) * jitter

所以设置 stream_max_retries = 10 后,各次等待约为:

1
0.2, 0.4, 0.8, 1.6, 3.2, 6.4, 12.8, 25.6, 51.2, 102.4 秒

第 10 次单次等待就约 102 秒,前 10 次累计约 205 秒。因此看到 10/10 时,程序很可能并没有死,只是在执行最后一次很长的 exponential backoff。

源码中的这套 backoff 没有为普通 stream retry 设置 60 秒上限:

此外,默认 stream_idle_timeout_ms300000,即 5 分钟。一次重试真正发出去后,如果连接没有事件,又可能继续等很久。

3. WebSocket fallback 还会重置计数

当普通 stream retry 用尽后,如果当前走 WebSocket,Codex 还会尝试 fallback 到 HTTPS,并把 stream retry 计数清零。

所以实际流程可能是:

1
2
3
4
5
WebSocket 重试 N 次

切换 HTTPS

重新获得 N 次 stream retry

这进一步说明 stream_max_retries 更接近“当前 transport 的 stream retry budget”,而不是整个 turn 的最大尝试次数。

4. 目前 config 能做到什么

如果目标是网络断掉后尽量一直等到恢复,可以保留:

1
2
[features]
unbounded_connection_retries = true

如果不希望 HTTP 内层再做一轮指数退避,可以把 provider 的:

1
request_max_retries = 0

同时不要把 stream_max_retries 设得太大。我现在更倾向于类似:

1
2
3
4
5
6
7
[features]
unbounded_connection_retries = true

[model_providers.example]
request_max_retries = 0
stream_max_retries = 5
stream_idle_timeout_ms = 30000

不过要注意:仅靠 config.toml 目前无法实现“所有 retryable error 都无限重试,并且固定间隔、不做指数退避”ConnectionFailed 的无限重试仍然会从 5 秒退避到 60 秒;其他 stream error 仍然使用有限次数的指数退避。要得到完全固定间隔的无限重试,只能修改 Codex 的 retry 实现。

结论

最需要记住的两点:

  1. stream_max_retries 不是整个 Codex turn 的最大重试次数;ConnectionFailed 默认可以无限重试。
  2. 把它从 5 调到 10 的代价远比“多重试 5 次”大,因为最后一次 backoff 已经增长到约 102 秒。

所以遇到 Reconnecting... 10/10 长时间不动时,先别急着判断死锁:它很可能只是 Codex 当前 retry 策略的正常结果。

About this Post

This post is written by KaranocaVe.

#Codex #CLI #OpenAI #Retry