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 自动升级引入新的不兼容

参考

相关推荐
Eiceblue1 小时前
Python 操作 Excel:数据分组、分类汇总与取消分组全解
开发语言·python·excel
暴躁小师兄数据学院2 小时前
【AI大模型应用开发工程师特训笔记】第04讲(第9章):文件目录操作
人工智能·笔记·python
TechWayfarer3 小时前
IP精准定位服务在快递网点规划中的应用:如何用客户位置数据辅助选址
大数据·网络·python·tcp/ip·交通物流
CSND7403 小时前
零基础学Python合集---3:字符串的定义和常用方法
人工智能·python
五月君_3 小时前
放弃 Python,Kimi 用 TS + Node.js 重写了一个 Kimi Code
开发语言·python·node.js
还是鼠鼠3 小时前
AI掘金头条新闻系统 (Toutiao News)-获取用户信息
后端·python·mysql·fastapi·web
Cloud_Shy6183 小时前
解读《Effective Python 3rd Edition》:从练气到老魔
开发语言·python
SunnyDays10113 小时前
Python 操作 Excel 超链接:添加网页、文件、工作表和图片链接
python·excel
li星野3 小时前
RAG优化系列:HyDE(假设文档嵌入)——让LLM先写答案再检索
python·学习