Skip to content

v0.3.7 — clean terminals on upstream connection failures

Choose a tag to compare

@dzshzx dzshzx released this 10 Jul 09:48

Fixed

  • Upstream transport failures no longer strand Codex in reconnect / "high demand" loops (#8). When the upstream — or a local forward proxy in front of it (e.g. Clash/Mihomo) — is temporarily unreachable (ConnectError, PoolTimeout, …), the proxy previously let the exception escape as a bare HTTP 500 or an abnormal WebSocket 1006 close, which Codex reads as backend trouble and keeps retrying. Now:
    • on the Responses path (WebSocket and POST SSE), the failure becomes a clean response.failed terminal with error.code: "upstream_connection_error";
    • on the /v1/* passthrough (e.g. GET /v1/models), it becomes a JSON 502 with the same code.
  • Round-open failures now carry a string error.code (e.g. "upstream_429" instead of numeric 429), matching the string codes already used on the WebSocket path.

Deliberately no retry on transport failures: send() can fail after the request has already reached the upstream (ReadTimeout, RemoteProtocolError), so a blind re-send would risk a duplicate, double-billed generation.

Thanks @steveoon for the fix (#9).


中文说明

修复上游(或其前置的本地代理,如 Clash/Mihomo)临时不可用时,ConnectError/PoolTimeout 等传输错误以裸 HTTP 500 / WebSocket 1006 异常关闭逃逸,导致 Codex 误判为后端故障而陷入 "high demand" 重连循环的问题(#8)。现在 Responses 路径返回干净的 response.failed 终端事件(error.code: "upstream_connection_error"),/v1/* 透传路径返回 JSON 502;round-open 错误码统一为字符串形式(如 "upstream_429")。传输失败刻意不重试——请求可能已到达上游,盲目重发有重复生成、重复计费的风险。感谢 @steveoon 的贡献(#9)。