Claude Code 一次更新引爆国产模型 400 错误

产品更新

Claude Code v2.1.154 引入新的 mid_conversation_system role,导致 DeepSeek、MiMo、GLM 等多个国产模型 API 全线报 400 错。各家渠道紧急适配,v2.1.156 已基本恢复正常。

Claude Code 一次小版本更新,把国产模型集体送进 400 错误

5 月 28 日凌晨,Anthropic 给 Claude Code 推了个看似平平无奇的小版本 v2.1.154。结果国内一觉醒来,论坛炸了——DeepSeek、MiMo、GLM 等几乎所有第三方模型渠道集体报 400 错误,CC 用户工作流直接瘫痪。

问题出在一个新引入的消息角色:mid_conversation_system

报错长什么样

用 DeepSeek 跑 Claude Code,你会看到这样一段眼熟又陌生的错误信息:

API Error: 400 Failed to deserialize the JSON body into the target type: 
messages[1].role: unknown variant `system`, 
expected `user` or `assistant` at line 1 column 2194

翻译过来就是:服务端在反序列化请求体时,发现 messages 数组里第二条消息的 role 字段值是 system,但它只认识 userassistant

这事儿乍一看莫名其妙。OpenAI 兼容格式不是一直支持 system role 吗?怎么突然就不认了?

实际上问题不在第三方渠道,而在 Claude Code 这次更新本身——v2.1.154 改了客户端构造请求的方式,会在对话中段插入 system 角色的消息(而不是只在数组开头出现一次 system prompt)。这种"对话中段 system 消息"在 OpenAI 官方规范里属于灰色地带,大多数兼容层的实现都只允许 system 出现在首条,后续只接受 user/assistant 交替。

Claude Code v2.1.154 在国产模型渠道下报 400 错误的终端截图

为什么是 mid_conversation_system

如果你翻 Claude Code 的 system prompts changelog 会发现,Anthropic 这段时间一直在重构 CC 的提示词架构。从 2.0 系列开始,他们就在往里塞越来越多的"过程性指令"——比如 TodoWrite 提醒、上下文压缩提示、工具调用的合规检查。这些指令本来是用 user 消息或者特殊 tag 注入的,但越用越乱。

v2.1.154 的解法是引入一个新角色 mid_conversation_system,专门用来在对话进行过程中向模型下达系统级指令,和初始 system prompt 区分开。听起来挺合理,问题是:

  • Anthropic 自家 API 认这个角色,因为他们的 schema 是私有的、可以随便加;
  • OpenAI 兼容协议不认,第三方实现按规范严格校验,自然就 400 了。

更让国内用户头疼的是:很多人用 Claude Code 时根本没在用 Anthropic 官方端点,而是通过中间网关把请求转发到 DeepSeek、Kimi、智谱 GLM、小米 MiMo 这些便宜大碗的国产模型。Anthropic 一改协议,整条链路全瘫。

这其实揭示了一个长期存在的脆弱性:Claude Code 作为客户端,对服务端协议有完全的塑造权,但下游兼容层永远在追着补丁跑。 这次只是改了个 role 名字,下次说不定就是改 tool_use 的结构,或者引入新的 content block 类型。

临时解法:先退回去

论坛上最早给出的方案简单粗暴——回退到 v2.1.153:

# 1. 关闭所有 Claude Code 终端
# 2. 全局安装上一版本
npm i -g @anthropic-ai/claude-code@2.1.153

这招对所有受影响的渠道都管用,因为 v2.1.153 还是老协议,不会发出 mid_conversation_system 这个新 role。

但回退不是长久之计。Claude Code 这两个月平均每周都有更新,新版本通常会带 bug 修复和小功能,长期锁死老版本意味着你享受不到 Anthropic 后续的优化。

渠道方的反应速度

这次国产渠道的响应速度其实挺快。截至 5 月 28 日下午 13:30 左右,MiMo Token Plan 率先完成服务端兼容性修复,做法是在反序列化层把 mid_conversation_system 静默映射为 system(或者根据上下文转成 user 消息),让请求能正常进入推理流程。

实测 Claude Code v2.1.156 在 MiMo 上已经完全正常,无需回退版本,也不需要在配置里加什么实验性开关屏蔽。之前回退到 2.1.153 的用户可以直接升回最新版继续用。

DeepSeek、GLM 的官方 API 和主流网关基本在同一天内也跟上了适配。如果你今天(5 月 29 日)还在遇到这个 400,大概率是用的某个小众第三方代理还没更新,建议先确认上游渠道版本。

这事儿暴露了什么

抛开具体的修复方案,这次小事故其实把"Claude Code + 第三方模型"这套用法的隐藏成本摆到了台面上。

第一个成本是协议追随。 Anthropic 没有义务保持向后兼容,CC 的协议本质上是它自己的内部事务,第三方拿来用就要承担随时被改的风险。这次是 role 字段,下次可能是别的。每次协议变化,全国大大小小的网关都得重新适配一遍。

第二个成本是行为对齐。 就算协议层兼容了,提示词差异也会让 DeepSeek/GLM 跑 CC 的效果和 Claude 原生差一截。Anthropic 的 system prompt 是针对 Claude 的训练分布精心调过的,换个底层模型,工具调用的成功率、TodoWrite 的执行稳定性都会打折扣。这次 mid_conversation_system 的引入就是为了让 Claude 更好地遵循中段指令——别的模型未必吃这一套。

第三个成本是调试体验。 当你的 CC 突然报错,你得先判断是 Anthropic 改了协议、还是渠道方没适配、还是你自己网络出问题。这次报错信息相对友好(Rust 风格的反序列化错误,明确指出哪个字段不对),但下一次未必。

给开发者的建议

如果你日常重度依赖 Claude Code,又想用国产模型省成本,几个实操建议:

  1. 不要在 CC 自动升级上太激进。npm i -g @anthropic-ai/claude-code@latest 改成手动升级,每次升级前看一眼论坛有没有人翻车。
  2. 关注你用的渠道的更新公告。 MiMo、DeepSeek 这些渠道一般会在协议变化时第一时间发通告。
  3. 多渠道备份。 在 CC 配置里准备两套 endpoint,主渠道挂了能立刻切到备用。像 OpenAI Hub 这种一个 Key 调所有主流模型的聚合服务(GPT、Claude、Gemini、DeepSeek 都覆盖),在协议变更时通常会在网关层统一处理掉,能省下不少自己排查的功夫。
  4. 保留一个能跑通的旧版本号在 README 里。 真出问题时回退最快。

小结

v2.1.154 → v2.1.156 这一波折腾,从凌晨爆雷到下午基本平息,前后不到 12 小时。对 Claude Code 这种活跃迭代的工具来说,这种小波折以后还会反复出现。技术上不算大事,但提醒大家:当你把一个由别人控制的客户端架在一堆兼容层之上,你的工作流就有了一个你看不见的依赖图。

现在可以放心升级回 v2.1.156,继续爽用。

参考来源