Claude Code 使用 DeepSeek 出现 API Error 400 错误的解决方案

最近 Claude Code 自动更新后,使用 DeepSeek 的用户陆续遇到 API Error: 400。这类错误最麻烦的地方在于:表面上都是 400,但背后的原因不一样。如果把不同版本、不同报错混在一起排查,很容易走错方向。

这篇只讨论 API Error: 400,不展开其他网络、账号、额度或模型能力问题。按时间顺序,先看最新的 Claude Code v2.1.154,再看更早的 2.1.152 附近问题。

最新问题:Claude Code v2.1.154 的 system role 报错

5 月 29 日,Claude Code 更新到 v2.1.154 后,使用 deepseek-v4-pro 时出现了下面这个 400 错误:

Claude Code v2.1.154
deepseek-v4-pro

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 9307

这个错误的重点不是 thinking,而是 messages[1].role。报错已经说得很清楚:目标接口只接受 user 或 assistant,但请求里出现了 system,于是 JSON 反序列化失败。

也就是说,这一类 400 更像是 Claude Code 新版本请求格式 与 DeepSeek 当前兼容接口或中间层 之间的不匹配。Claude Code 可能把系统提示作为 system role 放进消息数组,但 DeepSeek 这一路径并不接受这种 role。

解决方法

1、关闭 Claude Code 自动更新

2、降级到 v2.1.153 版本

我检索了公开搜索结果和 GitHub issue,目前没有找到与这条 messages[1].role: unknown variant `system` 完全一致的公开反馈。因此这条更适合写成当前环境中的实测案例,而不是说“已经大量用户公开反馈”。

154 版本的处理方案:

如果你遇到的是这条 system role 报错,优先不要去调 thinking。因为报错点已经明确指向 role 类型。

短期最直接的办法是关闭 Claude Code 自动更新,并回滚到确认可用的版本:

npm i -g @anthropic-ai/claude-code@2.1.153

长期修法则在兼容层:不要把 system role 原样转发给只接受 user 和 assistant 的接口。需要把 system message 转换成目标接口支持的系统提示字段,或者合并进 user message。

较早问题:Claude Code v2.1.152 附近的 thinking 回传报错

更早一次问题出现在 Claude Code 自动升级或重启后变成 152 版本附近。当时 DeepSeek 直接报:

API Error: 400 The `content[].thinking` in the thinking mode must be passed back to the API.

这条错误和 154 的 system role 不同。这里的关键是 content[].thinking。DeepSeek 的 thinking mode 要求客户端在后续请求中,把上一轮返回的 thinking 内容按要求带回去。如果客户端、中间层或会话恢复逻辑没有正确回传,就会被 API 拒绝。

152 附近问题的处理建议

如果你遇到的是 content[].thinking must be passed back,优先检查 thinking 相关逻辑,而不是 role。

短期方案有三种:

第一,回滚版本,例如:

npm i -g @anthropic-ai/claude-code@2.1.150

第二,禁用 DeepSeek 的 thinking / 深度思考能力。这个方法能绕开一部分 400,但代价是模型表现可能下降,复杂代码任务尤其明显。

第三,修改请求链路,确保 thinking blocks 在多轮对话、工具调用和会话恢复时完整回传。这是更接近根因的做法。

提醒和思考

第一,看到 API Error: 400 不要先入为主。400 只是说明请求不符合服务端要求,不代表所有 400 都是同一个问题。要先看报错里的关键词:是 system role,还是 content[].thinking,两者排查方向完全不同。

第二,Claude Code 自动更新对普通用户很方便,但对接 DeepSeek、Mimo 或其他第三方兼容层时,自动更新可能变成风险。因为 Claude Code 的消息格式只要稍微变化,兼容层就可能跟不上。

第三,DeepSeek 的 thinking mode 不是简单开关。它对历史消息、工具调用、会话恢复都有连续性要求。中间层如果为了兼容不同 provider 随手清理 thinking blocks,就可能让下一轮请求直接失败。

第四,回滚版本只是止血,不是根治。对使用者来说,回滚能最快恢复工作;但对维护兼容层的人来说,真正要修的是请求转换:thinking 要正确回传,system role 要正确转换。

第五,工具链稳定比追新更重要。Claude Code 更新当然有价值,但如果你正在做重要项目,最好固定一个已验证可用的版本。不要让自动升级在工作中途改变你的开发环境。

结论

这几次 Claude Code + DeepSeek 的 API Error: 400,要按报错内容拆开看。

最新的 2.1.154 问题,是 system role 不被目标接口接受;较早的 2.1.152 附近问题,是 content[].thinking 没有按 thinking mode 要求回传。

短期最稳的方案是关闭自动更新,并回滚到确认可用的 Claude Code 版本。长期来看,DeepSeek 兼容层需要同时处理好两件事:一是 thinking blocks 的多轮回传,二是 system role 的格式转换。