Claude Code 升级后 DeepSeek API 报错 messages[x].role: unknown variant system 终极解决方案

问题现象

使用 Claude Code(VSCode/Cursor 插件或 CLI)配合 DeepSeek API 时,报错:

text 复制代码
API Error: 400 Failed to deserialize the JSON body into the target type: 
messages[1].role: unknown variant system, expected user or assistant

claude --print 模式正常,但交互模式(IDE 插件)必现。

根本原因

Claude Code v2.1.153+ 在交互模式下,会将某些上下文指令(如 CLAUDE.md 内容、skills 注入等)以 role: "system" 的形式直接放入 messages 数组,而非 Anthropic 规范要求的顶层 system 参数。DeepSeek 的 /anthropic 兼容端点对此做了严格校验,直接拒绝。

本质上是 DeepSeek 的 Anthropic 兼容层对消息格式的容错不如官方 API。

环境变量方案(治标)

~/.claude/settings.jsonenv 中添加:

json 复制代码
{
  "env": {
    "ANTHROPIC_MODEL": "deepseek-v4-pro",
    "CLAUDE_CODE_DISABLE_NON_ESSENTIAL_BETAS": "1",
    "CLAUDE_CODE_BETAS": "",
    "DISABLE_AUTOUPDATER": "1"
  }
}

此方案通过禁用 Beta 功能来减少不兼容性,但实测不一定对所有版本/场景生效

本地代理方案(治本,推荐)

写一个 Python 代理,拦截 Claude Code 发出的请求,自动把 messages 数组中的 system 角色消息移到顶层 system 参数,再转发给 DeepSeek。

创建代理脚本 claude_proxy.py

python 复制代码
import http.server, json, urllib.request

TARGET = "https://api.deepseek.com/anthropic"
API_KEY = "你的DeepSeek-API-Key"
PORT = 9877

class Proxy(http.server.BaseHTTPRequestHandler):
    def do_POST(self):
        length = int(self.headers.get("Content-Length", 0))
        body = self.rfile.read(length)
        try:
            parsed = json.loads(body)
            msgs = parsed.get("messages", [])
            extra, cleaned = [], []
            for m in msgs:
                if m.get("role") == "system":
                    c = m.get("content", "")
                    extra.append(c if isinstance(c, str)
                        else " ".join(x.get("text","") for x in c
                            if x.get("type") == "text"))
                else:
                    cleaned.append(m)
            if extra:
                existing = parsed.get("system", "")
                if isinstance(existing, list):
                    existing = " ".join(
                        x.get("text","") for x in existing
                        if x.get("type") == "text")
                parsed["system"] = (existing + "\n\n" if existing else "") + "\n\n".join(extra)
                parsed["messages"] = cleaned
                body = json.dumps(parsed).encode()
        except:
            pass
        url = TARGET + self.path
        req = urllib.request.Request(url, data=body, method="POST")
        for k, v in self.headers.items():
            if k.lower() not in ("host", "content-length"):
                req.add_header(k, v)
        try:
            resp = urllib.request.urlopen(req, timeout=60)
            rbody = resp.read()
            self.send_response(resp.status)
            for k, v in resp.headers.items():
                if k.lower() not in ("transfer-encoding", "content-length", "connection"):
                    self.send_header(k, v)
            self.end_headers()
            self.wfile.write(rbody)
        except Exception as e:
            self.send_response(502)
            self.end_headers()
            self.wfile.write(str(e).encode())

    def log_message(self, f, *a):
        pass

http.server.HTTPServer(("127.0.0.1", PORT), Proxy).serve_forever()

启动代理

bash 复制代码
python claude_proxy.py

修改配置

修改 ~/.claude/settings.json,将 ANTHROPIC_BASE_URL 指向代理:

json 复制代码
{
  "env": {
    "ANTHROPIC_BASE_URL": "http://localhost:9877",
    "ANTHROPIC_MODEL": "deepseek-v4-pro"
  }
}

重启 Claude Code 即可

开机自启(可选)

代理默认只在当前会话运行,重启电脑后会停。设为开机自启:

Win+R → 输入 shell:startup → 回车,在该文件夹新建 claude_proxy.bat

batch 复制代码
@start /min python "文件路径\claude_proxy.py"

之后每次开机代理都会自动在后台运行,无需手动启动。

如果还不行:例如你装了别的智能体

在 Cursor/VSCode 的 settings.json 中加上:

batch 复制代码
{
  "claudeCode.environmentVariables": [
    { "name": "CLAUDE_CODE_DISABLE_NON_ESSENTIAL_BETAS", "value": "1" },
    { "name": "CLAUDE_CODE_BETAS", "value": "" },
    { "name": "DISABLE_AUTOUPDATER", "value": "1" }
  ]
}

CLAUDE_CODE_DISABLE_NON_ESSENTIAL_BETAS=1 禁掉了 Claude Code 新版本自动启用的 Beta 功能(如 interleaved-thinking、prompt-caching-scope),这些 Beta 会导致请求格式与 DeepSeek 的 Anthropic 兼容代理不兼容。

注意事项

  • 重启电脑后代理会自动停止,需重新启动 python claude_proxy.py
  • 如果 DeepSeek 后续修复了兼容性问题,可去掉代理恢复直连
  • 建议同时设置 DISABLE_AUTOUPDATER=1 防止 Claude Code 自动升级引入新的不兼容

参考

相关推荐
老白干37 分钟前
jjwt 0.9.1 在 JDK 11+ 上的两个“坑”与完整解决方案
java·python·log4j
笨鸟先飞,勤能补拙7 小时前
AI 赋能网络安全:技术全景、成熟度评估与实战案例
人工智能·python·安全·web安全·网络安全·sqlite·github
长和信泰光伏储能8 小时前
京津冀光伏发电:绿色能源的未来之路
python·能源
浦信仿真大讲堂8 小时前
从重复操作到自动化闭环:如何让 CST 与 Python 真正协同起来
python·自动化·cst·仿真软件·达索软件
Gu Gu Study9 小时前
ScoutLoop开放域深度研究引擎(agent的初步设计想法)
人工智能·python
卷无止境10 小时前
写代码这件事,到底该讲究点什么?
后端·python
卷无止境10 小时前
循环复杂度到底在算什么,Python 代码怎么才能写得让人一看就懂
后端·python
lpfasd12310 小时前
MediaCrawler 项目深度分析
chrome·python·chrome devtools
Dxy123931021610 小时前
Python项目打包成EXE完整教程(PyInstaller实战避坑)
开发语言·python
bamb0011 小时前
一个项目带你入门AI应用开发01
python