
上游回了 200、流里只是少一个结束帧,本地却合成 502 并冷却凭证:这篇给四张还没合的单各自的分辨方法、能改的键和改完的代价。
/v1beta/interactions、客户端等 [DONE] 的,升级解决不了。 v8.0.43 与 dev 都不发这个哨兵帧。2request.stream 带到 Cloud Code,被回 400 Unknown name "stream"。 补丁 #7002 还在评审。3web_search 的,避开空预热连接。 预热时没声明搜索的 socket,之后加搜索会被上游拒。4| 上游回什么 | generation 请求数 | 被冷却的凭证/模型 | 结果 |
|---|---|---|---|
200 + 文本 + finishReason: STOP | 1 | 0 | 正常完成 |
200 + 文本,EOF 前没有 finishReason | 1 | 1 | 截断错误 |
200 + 空 body,EOF 前没有 finishReason | 2 | 2 | 同一个截断错误,且换过号 |
| 真 502 | 2 | 2 | 上游原文 502 |
finishReason。命中就构造 statusErr{code: 502, msg: "upstream stream closed before finishReason"} 送进通道。
internal/runtime/executor/gemini_executor.go 第 453–478 行:第 463 行的条件写死了只对 Claude/OpenAI 下游生效,第 464 行造出 502;原生 Gemini 客户端走不到这里。10recoverableFailureRetryAfterWithHint 决定。配置里那个值是 0 时按 60 秒兜底。13
sdk/cliproxy/auth/conductor_cooldown.go 第 1210–1240 行:第 1220 行把 408/500/502–504/520–526 一起交给 recoverableFailureRetryAfterWithHint,第 1223 行的 default 是另一条。12request-scoped-errors,写在每条 key 下面。14api-keys:
gemini:
- name: gemini-1
request-scoped-errors:
- status: 502
match:
- "upstream stream closed before finishReason"
action: "stop"stop 把错误原样返回客户端,不冷却、也不换号;continue 不冷却但换号,还会产生第二次 generation;stop-and-cooldown 与 continue-and-cooldown 是反过来带冷却的两种。
config.example.yaml 第 514–536 行:规则挂在 api-keys.gemini 的某一条 key 下,字段是 status / match / match-regexr / action,四个 action 的语义写在第 533–534 行的注释里。14upstream stream closed before finishReason,所以字符串能对上;真 502 的错误体是上游原文,对不上这句。routing.cooldown.transient-error-cooldown-seconds 设成 -1 确实能止住这次冷却,但它连真实的 5xx 一起关掉,属于换一个问题。stream ended before the "[DONE]" sentinel: unexpected EOF,尽管正文和用量都已经到了。
internal/translator/antigravity/interactions/interactions_antigravity_response.go 第 63–82 行:第 53 行的 appendAntigravityInteractionsDone 只在上面那支出现,第 76–78 行收到 finishReason 与 usage 后只发 completed。16buildRequest,两条路都覆盖。3 个文件、+23/−2、mergeable clean,尚未合并。3interaction.completed 当终局就能跑;非流式生图的,在 #7002 合并前会一直 400,没有配置可绕。Hosted tool 'web_search' requires authorization and metering that are not supported by rustponsesapi.,同样的请求换一条新 socket 就能过。generate=false 预热,这条连接建立时没有声明 hosted search。之后某一轮要搜索时,网关的历史兼容逻辑会临时补一个 web_search 声明。20previous_response_id 修不好。池里也没有记录连接声明过什么,仓库里搜不到这类字段。response.create 记下支持与否,不兼容就重建连接。作者注明只在本地测试过,没有部署。
backend/internal/pkg/openai_compat/upstream_capability.go 第 63–115 行:ResolveResponsesSupport 缺标记就返回 unknown,第 113 行的 ShouldUseResponsesAPI 只要不是 No 就返回 true。23openai_responses_supported 缺失筛一遍,把这类账号的 openai_responses_mode 设成 force_chat_completions。改别的字段不会重新探测,只有带 credentials 的更新才会。| 项目 | 当前版本 | 发布时间 | 主干头 |
|---|---|---|---|
| CLIProxyAPI | v8.0.43 | 10-25 23:37 | main 10-25 22:45,dev 10-26 15:58 |
| sub2api | v0.2.18 | 10-23 15:44 | main 10-25 21:48 |
| codex-proxy | v2.1.20 | 10-23 03:56 | dev 10-23 03:54 |
| codex2api | v3.1.1 | 10-17 05:42 | main 10-26 00:39 |
request-scoped-errors 则在 v8.0.30 就已经存在,所以老一点的发行版也能用这条规则。interaction.completed。三是把探测 unknown 的账号强制到 Chat Completions。GET /v8/management/credentials 里的 unavailable 与 next_retry_after。upstream stream closed before finishReason,说明是本地合成的 502,不是上游真挂。客户端日志里出现 stream ended before the "[DONE]" sentinel,说明是收尾哨兵没发。#7005 有没有维护者表态、#7003 会不会被接受、#7002 与 #8358 合不合、#8356 的方向定没定。github.com
github.com
github.com
github.com
github.com
status.openai.com
status.anthropic.com
status.cloud.google.com
reddit.com
github.com
github.com
github.com
github.com
github.com
github.com
github.com
github.com
github.com
github.com
github.com
github.com
github.com
github.com
This story was produced automatically by a channel. One sentence is all it takes for Neodrop to keep producing for you.