Skip to content

[Bug] Codex 模型走 /v1/responses 返回上游 403 / no_usable_credential,而 /v1/chat/completions 正常 #268

Description

@qyh9527

概要

在我部署的 GPROXY 实例上,同一个模型 codex/gpt-6.1-sol 通过 /v1/chat/completions 和 /v1/messages 正常,但通过 /v1/responses 会返回一个带 OpenAI 品牌的 Cloudflare HTML 403 页面。之后继续请求 Responses 可能返回 503 no_usable_credential,而同一模型、同一网关密钥的 Chat Completions 仍然成功。

本 issue 报告的是观察到的现象,不是已确认的源码级根因。

环境

  • 测试日期:2026-09-30。
  • 本地源码检出:dev 分支,提交 1bd023743f67f7cd656f9eaf0f5018a26ef104ed。
  • 线上实例的确切版本 / 提交未经验证。 上述检出不可假定与运行中的服务端一致。
  • 测试期间网关健康端点返回 {"revision":113,"status":"ok"}。这是配置 revision,不是软件版本。
  • 本次排查未修改任何源码。

最小复现

使用有效的网关密钥和一个已配置的 Codex 模型,把下面的占位符替换为你自己的实例和凭据,所有请求超时 30 秒。

正常:Chat Completions

curl --max-time 30 -sS "$BASE_URL/v1/chat/completions" \
  -H "Authorization: Bearer $GPROXY_API_KEY" \
  -H 'Content-Type: application/json' \
  -d '{"model":"codex/gpt-6.1-sol","messages":[{"role":"user","content":"hi"}],"stream":false}'

失败:Responses

curl --max-time 30 -sS "$BASE_URL/v1/responses" \
  -H "Authorization: Bearer $GPROXY_API_KEY" \
  -H 'Content-Type: application/json' \
  -d '{"model":"codex/gpt-6.1-sol","input":[{"type":"message","role":"user","content":[{"type":"input_text","text":"hi"}]}],"stream":false}'

实际结果

请求 观察到的结果
/v1/chat/completions,非流式,codex/gpt-6.1-sol 200;连续 20 次请求全部成功
/v1/chat/completions,流式,同模型 200;可见内容分片、finish_reason: stop 以及 [DONE]
/v1/messages,同模型 200,返回助手文本
/v1/responses,同模型,非流式或流式 HTML 403 或 JSON 503
/v1/responses,其他已列出的 codex/ 模型 gpt-6-astra、gpt-6-luna、gpt-6-luna-fast 观察到类似失败
/v1/responses,非 Codex 对照组 grok/grok-4.7、cline/cline-pass/glm-5.3 以及另一条已配置路由均观察到 200 成功

HTML 403 内含 OpenAI 品牌、Unable to load site、指向 status.openai.com 的链接,以及一个内嵌的 IP / Ray ID。其内嵌 Ray ID 与 HTTP 响应外层的 CF-RAY 不同,支持该 HTML 来自另一个上游 Cloudflare 跳,而不是网关自身的认证层。

无效的网关认证返回的是网关正常的 JSON 401,而不是这个 HTML 页面。

JSON 503 的内容是:

{"error":{"code":"no_usable_credential","message":"the instance failed to process this request"}}

其中一段最终序列为:

Responses #1:     403 OpenAI 品牌 HTML
Responses #2-6:   503 no_usable_credential
紧接其后的 Chat Completions #1-2: 200

暂停 45 秒后,另一段序列是 403, 403, 403, 503。这与"临时性的凭据可用性 / 健康状态处理"一致,但冷却时长、健康状态的作用范围、以及是否由熔断器负责,均未确认。

改用字符串 input、数组 input、显式 store:false 或 stream:true 都无法解决 Responses 的失败。

预期行为

Responses 入口应当能为已配置的 Codex 模型正常工作,或者返回一个可操作的诊断信息,说明它的上游路径为什么与成功的 Chat Completions / Messages 路径不同。

如果上游请求在 provider 选择、operation 映射、连接配置、endpoint 覆盖或请求准备上存在差异,希望能得到定位该差异的指引。

排查线索(非已确认原因)

在本地 dev 检出的代码中:

  • crates/gproxy-channel/src/channels/codex/request.rs:operation_path() 把生成类操作映射到 /responses。
  • default_conversion_target() 选择 StreamGenerateContent / OpenAi。
  • native_dialects() 与 build() / prepare_with() 或许有助于对比"同方言 Responses 处理"与"转换后的 Chat Completions 处理"。

仍然需要服务端的上游 URL、被选中的 provider / credential、出站连接配置,以及经过脱敏的请求头对比。仅靠客户端测试无法证明成功与失败的请求使用了同一个上游凭据或同一条网络出口。

该 HTML 表明存在上游拒绝,但它本身并不证明这是纯 IP 封禁或 GPROXY 的代码缺陷。请协助判断这是路由 / 配置差异,还是请求准备问题。

本报告不包含任何 API 密钥、账号标识、服务器 IP 或会话令牌。

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions