现象
在 Codex Desktop 中使用 New Codex MultiRouter 路由(同时启用官方 OpenAI Codex 直连链路),跨模型续聊时(例如从 MiniMax-M3 切到 gpt-5.4 后继续同一 session),会稳定复现 400:
已确认事实
- 失败发生时已成功连上官方上游,没有连接/网络/认证失败。
route_resolved(route_missed=false)→ request_prepared → auth_prepared → upstream_send 全部成功。
- 上游明确返回
400,不是 5xx、不是 502、不是连接失败。
- 同一时间窗口内,另一个 session 用同一 provider、同一官方上游能稳定拿到
200。
- 错误字段是
input[3].content,不是 messages[N].tool_calls、不是 tool schema。
因此可以排除:
剩下的唯一合理解释是:把 Codex 内部的某条 developer 消息错误地映射成了 /responses 的 input[3]。
本地证据
1. 失败 session 路径:
~/.codex/sessions/2026/07/01/rollout-2026-07-01T21-19-01-019f1dd5-3b1c-7bd0-8184-c0764586e8ab.jsonl:3
2. 失败 session 中开场 developer 消息内容(role: developer,content 共 6 段):
<permissions instructions>
<app-context>
<collaboration_mode>
<apps_instructions>
<skills_instructions>
<plugins_instructions>
developer.content[3](第 4 段)原文:
<apps_instructions>
## Apps (Connectors)
Apps (Connectors) can be explicitly triggered in user messages in the format `[$app-name](app://{connector_id})`. Apps can also be implicitly triggered as long as the context suggests usage of available apps.
An app is equivalent to a set of MCP tools within the `codex_apps` MCP.
An installed app's MCP tools are either provided to you already, or can be lazy-loaded through the `tool_search` tool. If `tool_search` is available, the apps that are searchable by `tools_search` will be listed by it.
Do not additionally call list_mcp_resources or list_mcp_resource_templates for apps.
</apps_instructions>
3. ~/.cc-switch/logs/codex-router.log 中的命中记录(同一 session 多次复现):
codex-router.log:2316(model=gpt-5.4-mini,首次命中)
codex-router.log:2322(model=gpt-5.4)
codex-router.log:2742
codex-router.log:2753
codex-router.log:2807
codex-router.log:3433
codex-router.log:3811
codex-router.log:3817
codex-router.log:3847
所有命中都呈现同一 pattern:
effective_endpoint=/responses
responses_to_chat=false / responses_to_messages=false
status=400
body_summary=Invalid_'input[3].content':_array_too_long._Expected_an_array_with_maximum_length_0,_but_got_an_array_with_length_1_instead.
高概率定位
input[3].content 大概率对应的是 Codex 宿主注入的 developer 消息中的某一段。
需要说明的不确定性:
<apps_instructions> 本身不是 OpenAI Responses API 的请求字段,它只是 Codex 宿主拼到 developer.message.content 里的一段文本。
- 错误指向的是 message item 的 shape(
expected 0, got 1),不是文字内容本身。
- 当前没有抓到真实
/responses request body,因此 input[3] 究竟对应本地 developer.content[3],还是 ccswitchmulti 在拆分过程中把 developer 整条映射成了 input[3],仍需要抓包确认。
为什么不是现有 issue
临时规避
按效果由强到弱:
- 切模型时开新会话,不要 resume 同一个 thread
- 改用 OAI-compatible 端点,让代理走
responses_to_chat=true 路径,绕开官方 /responses 直连校验
- 改用
openai_chat 转换路径
注意:以上都不能根治问题。
建议方向
-
正确归类 Codex 内部的 developer 消息
- 它不是普通 user/assistant 消息
- 在
/responses 直连路径下,应当折叠到 instructions 或顶层 system,而不是按 content[i] 拆出多个 input[] 项
-
在 responses_to_chat=false / responses_to_messages=false 路径下,禁止把单条 developer message 的多段 content 拆成多个 message item
- 即使
/responses 直连,也应保持每个原始 message 一对一映射
-
补充诊断信息(最重要、最容易落地)
- 在
upstream_send 事件中新增可选的 body dump 字段(debug 级别或 env flag 控制)
- 这样社区用户在排障时能直接看到
input[N] 的真实 role 和 content 形状
- 当前只有
body_summary,无法定位根因
-
错误文案改进
-
针对 developer 消息加 unit test
- 输入:Codex 开场多段
developer message
- 期望:
/responses 直连模式下生成合法 input[]
- 当前应能复现
array too long
影响
期望维护者提供的信息
如果暂时无法复现,请至少提供以下任一项以确认根因:
- 在
upstream_send 时刻加 body 字段(debug 级 / env 控制),让我抓到真实 request body
- 一个能在本地复现的最小 Codex session(含
developer 消息)和当前 ccswitchmulti 版本
- 官方
/responses 是否对 input[N] 中 developer 消息的 content shape 有特定约束(如 content: "" 而非 content: ["..."])
现象
在 Codex Desktop 中使用
New Codex MultiRouter路由(同时启用官方OpenAI Codex直连链路),跨模型续聊时(例如从MiniMax-M3切到gpt-5.4后继续同一 session),会稳定复现400:用户侧报错:
codex-router.log中同一 trace 的 6 步事件:已确认事实
route_resolved(route_missed=false)→request_prepared→auth_prepared→upstream_send全部成功。400,不是5xx、不是 502、不是连接失败。200。input[3].content,不是messages[N].tool_calls、不是 tool schema。因此可以排除:
base_url缺失、auth 失败剩下的唯一合理解释是:把 Codex 内部的某条
developer消息错误地映射成了/responses的input[3]。本地证据
1. 失败 session 路径:
~/.codex/sessions/2026/07/01/rollout-2026-07-01T21-19-01-019f1dd5-3b1c-7bd0-8184-c0764586e8ab.jsonl:32. 失败 session 中开场
developer消息内容(role: developer,content共 6 段):<permissions instructions><app-context><collaboration_mode><apps_instructions><skills_instructions><plugins_instructions>developer.content[3](第 4 段)原文:3.
~/.cc-switch/logs/codex-router.log中的命中记录(同一 session 多次复现):codex-router.log:2316(model=gpt-5.4-mini,首次命中)codex-router.log:2322(model=gpt-5.4)codex-router.log:2742codex-router.log:2753codex-router.log:2807codex-router.log:3433codex-router.log:3811codex-router.log:3817codex-router.log:3847所有命中都呈现同一 pattern:
effective_endpoint=/responsesresponses_to_chat=false/responses_to_messages=falsestatus=400body_summary=Invalid_'input[3].content':_array_too_long._Expected_an_array_with_maximum_length_0,_but_got_an_array_with_length_1_instead.高概率定位
input[3].content大概率对应的是 Codex 宿主注入的developer消息中的某一段。需要说明的不确定性:
<apps_instructions>本身不是 OpenAI Responses API 的请求字段,它只是 Codex 宿主拼到developer.message.content里的一段文本。expected 0, got 1),不是文字内容本身。/responsesrequest body,因此input[3]究竟对应本地developer.content[3],还是ccswitchmulti在拆分过程中把developer整条映射成了input[3],仍需要抓包确认。为什么不是现有 issue
messages[8].tool_calls,本 issue 是input[3].content。Responses -> Chat转换时developerrole 映射为system,本 issue 走的是responses_to_chat=false的官方/responses直连路径。Responses -> OpenAI Chat转换时 tool schema 规范化,与本 issue 链路不重叠。临时规避
按效果由强到弱:
responses_to_chat=true路径,绕开官方/responses直连校验openai_chat转换路径注意:以上都不能根治问题。
建议方向
正确归类 Codex 内部的
developer消息/responses直连路径下,应当折叠到instructions或顶层system,而不是按content[i]拆出多个input[]项在
responses_to_chat=false/responses_to_messages=false路径下,禁止把单条developermessage 的多段content拆成多个 message item/responses直连,也应保持每个原始 message 一对一映射补充诊断信息(最重要、最容易落地)
upstream_send事件中新增可选的 body dump 字段(debug 级别或 env flag 控制)input[N]的真实role和content形状body_summary,无法定位根因错误文案改进
CC Switch local proxy failed误导性较强针对
developer消息加 unit testdevelopermessage/responses直连模式下生成合法input[]array too long影响
期望维护者提供的信息
如果暂时无法复现,请至少提供以下任一项以确认根因:
upstream_send时刻加body字段(debug 级 / env 控制),让我抓到真实 request bodydeveloper消息)和当前ccswitchmulti版本/responses是否对input[N]中developer消息的contentshape 有特定约束(如content: ""而非content: ["..."])