# Codex 报错 must have type response.create：先查本机 codex-router

> Codex 中途追问时报 must have type response.create，已知案例都出自本机 codex-router 旧版。更新到含修复的 main 即可，Homebrew 版暂未修复。

- Source: https://www.aifreeapi.com/zh/posts/codex-responses-websocket-must-have-type
- Language: zh
- Published: 2026-10-22
- Updated: 2026-10-22
- Publisher: AI Free API (https://www.aifreeapi.com)

回合进行中追问一句、回复问题卡片，或者中途打断，Codex 随即停下并显示：

```json
{"type":"error","status":400,"error":{"type":"invalid_request_error","message":"Responses WebSocket messages must have type response.create."}}
```

目前公开的案例里，这条报错都不是 OpenAI 服务器返回的，而是本机的 [codex-router](https://github.com/duolahypercho/codex-router)（一个让 Codex 接入 Kimi、DeepSeek 等外部模型的本机路由代理）写出来的。旧版 codex-router 在 WebSocket 连接上只接受 `response.create` 这一种消息；Codex 在回合中途收到你的新输入时，会在同一条连接上再发一条 `response.interrupt`，旧版代理把它当成非法请求，回了 400，这个回合就断了。

修复已经在 2026 年 10 月 12 日合并进 codex-router 的 main 分支（[PR #1004](https://github.com/duolahypercho/codex-router/pull/1004)）。你该做什么，取决于 codex-router 是怎么装的：

| 你的情况 | 下一步 |
| --- | --- |
| 用 README 推荐的一行安装脚本装的（受管 Git checkout） | `./bin/model-router codex update`，再 `./bin/model-router codex doctor --fix`，完全退出并重开 Codex |
| 用 Homebrew 装的 | 截至 2026 年 10 月 22 日，`brew upgrade` 只能拿到不含修复的 v0.6.0；先用临时办法，或改用安装脚本 |
| 暂时不能动 codex-router | 在 `[features]` 下写 `instant_interrupt = false`，未经实测，追问要等当前步骤结束 |
| 已经不需要外部模型 | `codex-router uninstall`（Homebrew）或 `./bin/model-router codex uninstall`（checkout） |
| `config.toml` 里没有任何本机代理 | 不属于这个已知原因，按后文的方式到 [openai/codex #52221](https://github.com/openai/codex/issues/52221) 报告 |

## 这条 400 是谁报的：本机 codex-router，不是 OpenAI

Codex 和模型服务之间通常走 Responses WebSocket：一条长时间保持的连接，双方在上面一条一条地发 JSON 消息（也叫“帧”）。每开始一个回合，Codex 发一条 `type` 为 `response.create` 的消息。

在 codex-router 0.6.0 和修复之前的 main 代码里，`src/responses-websocket.mjs` 有一道检查：收到的消息只要 `type` 不是 `response.create`，就回 HTTP 400、`invalid_request_error` 和这句原文（[codex-router #1019](https://github.com/duolahypercho/codex-router/issues/1019) 引用了这段代码）。报错里的英文句子就是这样来的。

### 为什么只在回合中途追问时出现

截至 2026 年 10 月 22 日，Codex 源码里有一个默认开启的功能 `instant_interrupt`。开启时，回合进行中你发追问、回复问题卡片（英文界面里叫 follow-up、question card，也就是“中途引导”，steering），Codex 会抢占正在生成的响应：在同一条连接上发出第二条消息，并等待 `response.interrupt.accepted` 或 `response.interrupt.failed` 的回复：

```json
{"type":"response.interrupt","response_id":"…","mode":"discard_partial_items"}
```

这段逻辑在 openai/codex 源码的 [`responses_websocket.rs`](https://github.com/openai/codex/blob/main/codex-rs/codex-api/src/endpoint/responses_websocket.rs) 里，只在响应已经开始之后才会发出。所以安静地等回合跑完不会触发报错，回合中途一插话就会。#52221 里的报告者在日志中也看到同样的顺序：先是 `TurnInput mode: Steer`，紧接着就是这个 400。

![时序示意：Codex 先在同一条连接上发送 response.create，被 codex-router 放行并转发；中途追问时再发送 response.interrupt，旧版 codex-router 回 HTTP 400，回合中断；修复后两种消息都放行，同一条连接继续可用](https://www.aifreeapi.com/posts/zh/codex-responses-websocket-must-have-type/img/interrupt-frame-sequence.webp)

有人猜 Codex 发的是 `response.steer`。OpenAI 公开的 [steering 指南](https://developers.openai.com/api/docs/guides/steering)确实为中途引导定义了 `response.steer`，但截至 2026 年 10 月 22 日，Codex 源码里中途打断发的是 `response.interrupt`，后者在公开的 API 指南里没有记载。对一个只放行 `response.create` 的代理来说，这两种消息都会被拒。

### 用 gpt-6.1-sol 这类原生模型也会出现

很多人装 codex-router 是为了接外部模型，切回 OpenAI 的原生模型后，不会想到请求还在经过它。原因在 codex-router 写进 `~/.codex/config.toml` 的受管配置块：

```toml
# BEGIN codex-router-managed
openai_base_url = "http://127.0.0.1:4202/_codex-router/<generated-capability>/v1"
...
# END codex-router-managed
```

`openai_base_url` 改的是 Codex 内置 OpenAI provider 的地址，所以原生 GPT 模型的回合同样发到 `127.0.0.1:4202`，经由 codex-router 转发。#52221 里使用 gpt-6.1-sol 的几位报告者，事后检查配置时都发现了这一行。

这是 codex-router 旧版与 Codex 中途打断机制之间的兼容缺口，codex-router 上游已经修复。

## 三处确认：config.toml、报错末尾、codex-router 版本

### 1. config.toml 有没有把请求导向本机代理

macOS / Linux：

```bash
grep -nE "openai_base_url|4202|codex-router" ~/.codex/config.toml
```

Windows PowerShell：

```powershell
Select-String -Path "$env:USERPROFILE\.codex\config.toml" -Pattern "openai_base_url","4202","codex-router"
```

看到 `openai_base_url` 指向 `127.0.0.1:4202`，或者有 `# BEGIN codex-router-managed`、`[model_providers.codex-router]`，就说明 Codex 的请求经过 codex-router。不熟悉这个文件的位置和结构，可以先看[《Codex 沙箱与 config.toml：权限、批准和网络怎么配》](/zh/posts/codex-config-toml)。

**注意：** `_codex-router/` 后面那一段是本机调用的凭证。不要把完整地址贴进 issue、群聊或截图，需要说明时写成 `127.0.0.1:4202/…/v1`。

### 2. 报错末尾是 response.create 还是 or response.interrupt

修复之后，codex-router 的检查同时放行 `response.create` 和 `response.interrupt`，遇到其他类型时的报错文字也变了：

| 报错结尾 | 说明 |
| --- | --- |
| `must have type response.create.` | 正在运行的 codex-router 早于修复 |
| `must have type response.create or response.interrupt.` | 已是修复后的版本，Codex 发了 codex-router 仍不认识的另一种消息，属于新问题 |

### 3. codex-router 版本是否包含修复

用安装脚本装的，checkout 默认在 `~/.local/share/codex-router`（macOS / Linux）。修复的合并提交是 `a0ceb5e6`：

```bash
git -C ~/.local/share/codex-router merge-base --is-ancestor a0ceb5e6dd9c5c4322cf8405620af607f226ca95 HEAD && echo "已包含修复" || echo "未包含修复"
```

用 Homebrew 装的：

```bash
brew list --versions codex-router
```

输出 `codex-router 0.6.0` 就是不含修复的版本。

代码更新了不等于已经生效：更新前启动的 codex-router 进程会一直跑旧代码，直到它重启。

另外可以运行 `codex features list`，看 `instant_interrupt` 一行的状态。如果它已经关闭，报错却照样出现，就超出了上面的解释，按最后一节的方式报告。

## 一行安装脚本装的：更新到 main 并运行 doctor --fix

```bash
cd ~/.local/share/codex-router
./bin/model-router codex update
./bin/model-router codex doctor --fix
```

几个前提和细节（来自 [codex-router README](https://github.com/duolahypercho/codex-router#updates-and-rollback)）：

- `update` 要求当前在 `main` 分支，且没有改动过被跟踪的文件；未跟踪的文件不影响。加 `--force` 会丢弃被跟踪文件的改动。
- 更新前的版本会保留为本地回滚点，有问题可以 `./bin/model-router codex rollback`。
- 已经手动 `git pull` 过，也照样跑一次 `update`。重新运行安装脚本同样会从 `main` 更新。
- `doctor --fix` 让生成的配置和后台服务跟新代码对齐。之后完全退出 Codex（不只是关窗口）再重新打开；如果 codex-router 是在前台终端里跑的，手动重启它。

改完用上一节第 3 步再确认一次，然后在回合进行中发一句追问试试。#52221 里有位 Windows 用户把这个修复移植到本机后，在桌面版里回复问题卡片，回合正常继续了；这只是一次测试，不代表长期稳定。

修复后的行为是：收到 `response.interrupt` 时取消本机发往上游的请求，丢弃未完成的内容，以 `response.incomplete`（原因 `interrupted`）结束这次响应，同一条连接继续可用。PR 里也写明，它取消的是本机的 HTTP 请求，不保证外部模型服务停止对已经发出的生成计费。用按量付费的外部模型时，频繁中途打断仍可能产生费用。

## Homebrew 装的：brew upgrade 截至 10 月 22 日拿不到修复

codex-router 最新的正式版本是 2026 年 9 月 15 日发布的 v0.6.0，早于 10 月 12 日合并的修复；Homebrew 公式下载的正是 v0.6.0 的源码包。所以截至 2026 年 10 月 22 日，`brew upgrade codex-router` 不会带来这个修复。

![codex-router 的两条更新线：Homebrew 从 9 月 15 日起停在 v0.6.0，brew upgrade 拿不到修复；安装脚本跟随 main，10 月 12 日合并 PR #1004（a0ceb5e6）后已含修复；更新后需运行 doctor --fix 并重开 Codex](https://www.aifreeapi.com/posts/zh/codex-responses-websocket-must-have-type/img/router-fix-release-lines.webp)

可以这样选：

- **愿意等下一个版本**：关注 [releases 页面](https://github.com/duolahypercho/codex-router/releases)，新版本发布后再 `brew upgrade codex-router`，等待期间用下一节的临时办法。
- **想马上修好**：先 `codex-router uninstall` 移除后台服务和受管的 Codex 配置，再 `brew uninstall codex-router`，然后按 README 改用推荐的安装脚本。安装脚本会从 `main` 拉代码，并重新引导你选择 provider。

## 暂时不能更新：instant_interrupt = false 的代价

在 `~/.codex/config.toml` 里加入：

```toml
[features]
instant_interrupt = false
```

文件里已经有 `[features]` 表时，把这一行加到原有的表下面，不要再写一个 `[features]`，否则 TOML 会因为重复的表而解析失败。保存后完全退出并重开 Codex。

按 Codex 源码的逻辑，关掉 `instant_interrupt` 后，中途追问不再抢占正在运行的响应，也就不会发出 `response.interrupt`。代价是追问要等当前这一步结束才生效，中途纠偏会慢一些。这个办法没有经过实测，#52221 里最早指出原因的评论者也说自己没有试过；`instant_interrupt` 在源码里仍标为开发中的功能，后续版本可能改名或移除。

把它当成过渡手段：codex-router 更新到含修复的版本后，删掉这一行。

## 不再需要外部模型：用 uninstall 或 disable 绕开代理

如果你已经不用通过 codex-router 接入的模型，直接把它从 Codex 的请求路径上拿掉：

| 安装方式 | 命令 |
| --- | --- |
| Homebrew | `codex-router uninstall`，之后可以 `brew uninstall codex-router` |
| 安装脚本（checkout） | `./bin/model-router codex uninstall`；只想移除 Codex 集成、保留其他部分，用 `./bin/model-router codex disable` |

README 建议用这些命令，而不是手动删除 `config.toml` 里的受管配置块。执行后 `openai_base_url` 不再指向 `127.0.0.1:4202`，原生模型直接连 OpenAI。#52221 里有用户移除 codex-router 后，这条报错就不再出现。代价是经 codex-router 接入的 Kimi、DeepSeek 等外部模型在 Codex 里用不了了。checkout 方式的 `uninstall` 会保留代码、日志、备份和 provider 凭证，之后想恢复不必从头配置。

## 这条 400 的相关疑问：追问会不会丢、Remote 会不会出现

### 这是 OpenAI 服务器的故障吗？

已知案例不是。报错文字出自 codex-router 的源码；附带配置信息的报告里，`openai_base_url` 都指向本机地址，其中多数写明是 codex-router 的 `127.0.0.1:4202`。截至 2026 年 10 月 22 日，OpenAI 还没有在 #52221 里回复。

### brew upgrade codex-router 能修好吗？

截至 2026 年 10 月 22 日不能。Homebrew 公式固定在 v0.6.0，修复只在 `main` 上，要等下一个正式版本。

### 被打断时，追问的内容会丢吗？

没有定论。有用户在 iPhone 上的 Codex Remote 里看到回合仍显示进行中，并出现 **Continue** 按钮；也有 Windows 用户反映，回复问题卡片后看不到预期的回答，只剩已执行命令的卡片。重试之前，先把追问的内容复制出来。

### 用 iPhone 上的 Codex Remote 也会出现吗？

会，已经有人在 Remote 对话里遇到。那位用户连接的 Mac 上，`openai_base_url` 同样指向 `127.0.0.1:4202`。要检查和修复的是运行 Codex 的那台电脑，不是手机。

### 能保留 codex-router，又正常中途追问吗？

能。把 codex-router 更新到包含 PR #1004 的版本即可，这正是修复的目的。更新前想继续用外部模型，就先用 `instant_interrupt = false` 过渡。

### 压缩失败之后才开始出现，两者有关系吗？

有 Windows 用户第一次遇到这条报错，是在一次上下文压缩失败之后，但他自己也无法确认两者有因果关系。压缩失败本身怎么处理，见[《Codex 远程压缩失败：先看完整报错，再决定重试还是恢复会话》](/zh/posts/codex-remote-compact-task-error)。

## 没有本机代理也出现这条报错：到 #52221 报告

如果 `config.toml` 里既没有 `openai_base_url`，也没有指向本机的自定义 provider，这条报错就超出了已知原因。#52221 中指出 codex-router 原因的评论者也说，没有代理的情况属于另一个原因，issue 应该为此保持打开。

到 [openai/codex #52221](https://github.com/openai/codex/issues/52221) 补充时，带上这些信息：

- Codex 桌面版或 CLI 的版本号，以及操作系统；
- 出错的时间和时区；
- 是否设置了 `openai_base_url` 或自定义 provider（写“是／否”和主机端口即可）；
- `codex features list` 里 `instant_interrupt` 那一行；
- 出错前你做了什么：追问、回复问题卡片，还是点了停止。

不要附上凭证、本机代理的完整地址或私人对话内容。

如果你已经更新了 codex-router，报错变成了以 `or response.interrupt.` 结尾的新文字，问题在 codex-router 这一侧，到它的 [issue 区](https://github.com/duolahypercho/codex-router/issues)报告更合适。

如果看到的不是这个 400，而是界面反复出现 `Reconnecting`，那是另一类连接问题，见[《Codex 一直 Reconnecting：先保住任务，再定位是哪一层断了》](/zh/posts/codex-stuck-reconnecting-fix)。

## 自己维护 Responses 网关：同时放行 response.interrupt

如果你自己写或维护一个给 Codex 用的 Responses 代理，这次的教训是：WebSocket 连接上不只会出现 `response.create`。

- **处理 `response.interrupt`**：字段是 `response_id` 和 `mode: "discard_partial_items"`，Codex 等的回复是 `response.interrupt.accepted` 或 `response.interrupt.failed`。这个事件在公开的 API 指南里没有记载，以 Codex 源码为准。
- **考虑 `response.steer`**：这是 OpenAI 公开文档里的中途引导事件，只用于 GPT-6 系列、只走 WebSocket，被引导的响应以 `response.incomplete`（原因 `steered`）结束。
- **按已知类型校验，不要一律放行**：codex-router #1019 期望的做法，是对支持的类型逐一处理，对未知类型返回清楚的错误，同时保证之后的 `response.create` 能在同一条连接上继续。
- **暂时不支持 WebSocket**：自定义 provider 可以在 `[model_providers.*]` 里声明 `supports_websockets = false`，让 Codex 改走 HTTPS（Coder AI Gateway 的文档给出了这个办法）。这只适用于自定义 provider；`openai_base_url` 改道的是内置 OpenAI provider，它默认开启 WebSocket。HTTPS 路径下中途引导是否表现一致，公开资料没有说明。

自定义 provider 的写法和逐项验证方法，见[《Codex 接第三方模型 API：先确认 Responses 兼容，再写 provider》](/zh/posts/codex-third-party-api)。
