[Bug] Codex API sidecar 首包超时后持续 504 / client_canceled,需重启 API 服务恢复

Author: Yurdos-rCreated Aug 11, 2026Updated Sep 17, 2026

问题描述

Codex API 的 sidecar 在某次上游首包(stream_open)超时后,会间歇或连续返回 HTTP 504。Cockpit 将这类错误记录为 client_canceled / context canceled。出现后,需要重启 API 服务(即重启 cockpit-cliproxy sidecar)才能恢复;期间 FlClash 及代理本身仍可正常使用,也无需切换代理节点。

这看起来不是单次上游慢响应,而是超时后 sidecar 的连接池、请求上下文、账号调度或会话缓存没有被正确清理,导致进程进入异常状态。

可能与 #1791、#967 相关,但这里补充了固定超时节拍、重启恢复和配置未真正重载的证据。

环境

  • Cockpit Tools: 1.3.16
  • OS: Windows 11 专业版 10.0.26200 x64
  • Gateway mode: sidecar
  • Model: gpt-5.6-sol
  • Proxy: http://127.0.0.1:7890(故障期间代理端口和其他网络请求正常)
  • OAuth 账号池: 3 个账号
  • Routing: round-robin
  • 当前相关配置:
    • stream-open-timeout-ms: 30000
    • stream-open-max-attempts: 3
    • stream-idle-timeout-ms: 300000
    • keepalive-seconds: 15
    • session-affinity: false(见下方“附加发现”)

实际表现

一次故障窗口内连续出现 4 次目标错误:

完成时间(UTC+8) HTTP 耗时 分类 错误
20:05:51 504 90.367s client_canceled Post https://chatgpt.com/backend-api/codex/responses: context canceled
20:07:22 504 90.384s client_canceled 同上
20:08:52 504 90.369s client_canceled 同上
20:10:23 504 90.368s client_canceled 同上

详细日志显示同一请求按约 30 秒的固定节拍重试三次,最终约 90.3 秒返回 504。这与 30 秒 × 3 次 的 sidecar 首包超时策略完全一致,因此 client_canceled 并不是客户端主动取消,而是 sidecar 的超时器取消请求上下文。

历史 debug 记录中,成功首包的 P99 约为 19.7 秒,最慢成功首包达到 34.291 秒,另一个为 29.740 秒。因此 30 秒阈值已经会取消至少一个原本能够成功的慢启动请求。

重启恢复证据

在不修改 FlClash、代理节点或系统网络的情况下,仅重启 Cockpit API 服务:

  • 新 sidecar 进程于 20:12:59 启动;
  • 随后的观察窗口中共 199 个请求:196 成功,3 个为 HTTP 200 下的正常客户端中途取消;
  • 0 个 HTTP 502;
  • 0 个 HTTP 504;
  • 最长请求 56.358 秒。

这说明恢复动作主要清除了 sidecar 的进程内状态或旧连接,而不是修复了外部代理网络。

附加发现:配置保存后旧进程仍在服务

此前尝试关闭会话亲和时,sidecar 重启失败:

listen tcp 127.0.0.1:<port>: bind: Only one usage of each socket address ... is normally permitted.

旧 sidecar 随后继续提供服务,导致界面/配置文件看似已经修改,但运行进程没有真正加载新配置。配置直到 20:12:58 再次写入并在 20:12:59 成功启动新进程后才生效。

期望行为

  1. stream_open 超时后应彻底释放/淘汰对应的请求上下文与 HTTP/TLS 连接,不应让后续请求持续复用异常状态。
  2. 重试时应建立新连接,并排除刚刚发生首包超时的账号/凭据,避免重复命中同一异常路径。
  3. sidecar 自己触发的超时应分类为类似 upstream_stream_open_timeout,不应记录为 client_canceled
  4. 配置重启若因端口占用失败,界面应明确显示配置尚未生效,并确保旧、新进程切换是原子的。
  5. 建议默认首包阈值覆盖已观测到的 34.291 秒成功尾部,或将该阈值及重试策略明确暴露为可配置项。

复现说明

该问题为间歇性,通常发生在较长的 Codex 流式请求或上下文较大时:

  1. 使用 sidecar 网关发送 gpt-5.6-sol 流式请求。
  2. 某次上游首包迟迟未返回。
  3. 观察到请求每 30 秒被取消并重试,三次后约 90 秒返回 504。
  4. 后续请求可能继续间歇或连续失败。
  5. 仅重启 API 服务后恢复,无需修改代理。

报告中的邮箱、API Key、完整账号 ID、请求正文和代理节点名称均已移除。