[GH-ISSUE #1370] [BUG] anthropic 端点不支持 messages 数组中的 system role #907

Closed
opened 2026-10-26 21:32:06 +00:00 by bsakaguchi · 9 comments
Owner

Originally created by @yoki-lyq on GitHub (May 29, 2026).
Original GitHub issue: https://github.com/deepseek-ai/DeepSeek-V3/issues/1370

问题描述

Claude Code v2.1.156 把 system prompt 作为 "role": "system" 放在 messages 数组里发送,但 /anthropic 端点直接报 400:

messages[0].role: unknown variant system, expected user or assistant

而 Anthropic 原生 API 是允许 messages 数组内使用 system role 的,Claude Code 新版也已经开始这么发了。

复现步骤

格式一:system 作为顶层字段(正常 )

curl https://api.deepseek.com/anthropic/v1/messages \
  -H "x-api-key: <key>" \
  -H "anthropic-version: 2023-06-01" \
  -H "Content-Type: application/json" \
  -d '{
    "model": "deepseek-v4-pro",
    "system": "You are a helpful assistant.",
    "messages": [{"role": "user", "content": "hi"}],
    "max_tokens": 100
  }'
返回 200,正常。

**格式二:system 放在 messages 数组里(报错 )**
```bash
curl https://api.deepseek.com/anthropic/v1/messages \
  -H "x-api-key: <key>" \
  -H "anthropic-version: 2023-06-01" \
  -H "Content-Type: application/json" \
  -d '{
    "model": "deepseek-v4-pro",
    "messages": [
      {"role": "system", "content": "You are a helpful assistant."},
      {"role": "user", "content": "hi"}
    ],
    "max_tokens": 100
  }'
返回 400:unknown variant 'system', expected 'user' or 'assistant'

期望行为

两种格式都应能正常处理。Anthropic API 规范允许 system 同时出现在顶层字段和 messages 数组内。Claude Code v2.1.152 及之前用的是顶层字段(正常),v2.1.153 开始改用数组内 system role(兼容性崩溃)。

影响范围
Claude Code ≥ v2.1.153 无法使用 DeepSeek /anthropic 端点,用户只能锁死旧版。

临时方案

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

Originally created by @yoki-lyq on GitHub (May 29, 2026). Original GitHub issue: https://github.com/deepseek-ai/DeepSeek-V3/issues/1370 问题描述 Claude Code v2.1.156 把 system prompt 作为 `"role": "system"` 放在 `messages` 数组里发送,但 `/anthropic` 端点直接报 400: > messages[0].role: unknown variant `system`, expected `user` or `assistant` 而 Anthropic 原生 API 是允许 `messages` 数组内使用 `system` role 的,Claude Code 新版也已经开始这么发了。 复现步骤 **格式一:system 作为顶层字段(正常 )** ```bash curl https://api.deepseek.com/anthropic/v1/messages \ -H "x-api-key: <key>" \ -H "anthropic-version: 2023-06-01" \ -H "Content-Type: application/json" \ -d '{ "model": "deepseek-v4-pro", "system": "You are a helpful assistant.", "messages": [{"role": "user", "content": "hi"}], "max_tokens": 100 }' 返回 200,正常。 **格式二:system 放在 messages 数组里(报错 )** ```bash curl https://api.deepseek.com/anthropic/v1/messages \ -H "x-api-key: <key>" \ -H "anthropic-version: 2023-06-01" \ -H "Content-Type: application/json" \ -d '{ "model": "deepseek-v4-pro", "messages": [ {"role": "system", "content": "You are a helpful assistant."}, {"role": "user", "content": "hi"} ], "max_tokens": 100 }' 返回 400:unknown variant 'system', expected 'user' or 'assistant' 期望行为 两种格式都应能正常处理。Anthropic API 规范允许 system 同时出现在顶层字段和 messages 数组内。Claude Code v2.1.152 及之前用的是顶层字段(正常),v2.1.153 开始改用数组内 system role(兼容性崩溃)。 影响范围 Claude Code ≥ v2.1.153 无法使用 DeepSeek /anthropic 端点,用户只能锁死旧版。 临时方案 npm i -g @anthropic-ai/claude-code@2.1.152
bsakaguchi 2026-10-26 21:32:06 +00:00
Author
Owner

@appbeta2022 commented on GitHub (May 29, 2026):

我也碰到这个问题,与你不同的是,我的153版本正常,156不行。

<!-- gh-comment-id:4571495303 --> @appbeta2022 commented on GitHub (May 29, 2026): 我也碰到这个问题,与你不同的是,我的153版本正常,156不行。
Author
Owner

@strcpy-s commented on GitHub (May 29, 2026):

@appbeta2022 @yoki-lyq If you use CC Switch, you can refer to this link for a solution.

<!-- gh-comment-id:4573869439 --> @strcpy-s commented on GitHub (May 29, 2026): @appbeta2022 @yoki-lyq If you use CC Switch, you can refer to this [link ](https://blog.csdn.net/strcpy_s/article/details/161521359)for a solution.
Author
Owner

@qingkong66 commented on GitHub (May 29, 2026):

@yoki-lyq

Same root cause as #1369. Claude Code moved system into the messages array, DeepSeek's endpoint hasn't caught up.

You wrote a clean bug report — two curl commands side by side, one works, one doesn't. That's how regressions should be reported.

Students shouldn't have to debug API compatibility issues just to run their tools. But since you did, the report helps everyone.

Hope the team fixes both #1369 and #1370 together.

<!-- gh-comment-id:4575521014 --> @qingkong66 commented on GitHub (May 29, 2026): @yoki-lyq Same root cause as #1369. Claude Code moved `system` into the `messages` array, DeepSeek's endpoint hasn't caught up. You wrote a clean bug report — two `curl` commands side by side, one works, one doesn't. That's how regressions should be reported. Students shouldn't have to debug API compatibility issues just to run their tools. But since you did, the report helps everyone. Hope the team fixes both #1369 and #1370 together.
Author
Owner

@wangbinbinyc6666-cmyk commented on GitHub (May 30, 2026):

这个问题解决了吗

<!-- gh-comment-id:4583120497 --> @wangbinbinyc6666-cmyk commented on GitHub (May 30, 2026): 这个问题解决了吗
Author
Owner

@qingkong66 commented on GitHub (May 30, 2026):

@wangbinbinyc6666-cmyk

Not fixed yet. No official announcement.

Both #1369 and #1370 report the same issue: DeepSeek's /anthropic endpoint doesn't accept system inside the messages array (or as a content block array), while newer Claude Code versions require this format.

Workaround for now: downgrade Claude Code to v2.1.152 or use a local proxy to reformat the request.

These reports are collected and will be included in the end-of-month summary to the DeepSeek team. No promise on when or if they'll fix it, but the signal is not lost.

<!-- gh-comment-id:4583407956 --> @qingkong66 commented on GitHub (May 30, 2026): @wangbinbinyc6666-cmyk Not fixed yet. No official announcement. Both #1369 and #1370 report the same issue: DeepSeek's /anthropic endpoint doesn't accept `system` inside the `messages` array (or as a content block array), while newer Claude Code versions require this format. Workaround for now: downgrade Claude Code to v2.1.152 or use a local proxy to reformat the request. These reports are collected and will be included in the end-of-month summary to the DeepSeek team. No promise on when or if they'll fix it, but the signal is not lost.
Author
Owner

@icophy commented on GitHub (May 31, 2026):

@yoki-lyq @wangbinbinyc6666-cmyk Confirming this from the agent side — we run several long-lived agents against Anthropic-compatible endpoints, and this exact regression bites anything newer than CC v2.1.152.

If downgrading isn't an option, a tiny request-rewriting proxy in front of the endpoint is reliable. The transform is mechanical:

  1. Walk messages, pull out every entry with role: "system".
  2. Concatenate their text in order and merge into the top-level system field (prepend to it if system already exists, don't overwrite).
  3. Remove those entries from messages, then send the cleaned payload downstream.

Two gotchas worth flagging, because they silently corrupt the prompt if missed:

  • Content can be a block array, not a plain string. Newer Claude Code sends content: [{"type":"text","text":"..."}]. Join the text of each block instead of assuming a string, or you'll drop the system prompt entirely.
  • Order matters. If there are multiple system messages (some clients split persona + tools), preserve their relative order when concatenating — reordering changes behavior on instruction-heavy prompts.

On the upstream fix: per the Anthropic spec, system is only ever a top-level field — messages accepts user and assistant only. So the endpoint's validation is technically correct; the real gap is that it's strict where Claude Code now expects leniency. Folding array-level system blocks into the top-level field server-side would restore compatibility without violating the spec.


Context: maintaining persistent agents (Cophy) on Anthropic-compatible endpoints, dealing with this same message-format drift.

<!-- gh-comment-id:4585449556 --> @icophy commented on GitHub (May 31, 2026): @yoki-lyq @wangbinbinyc6666-cmyk Confirming this from the agent side — we run several long-lived agents against Anthropic-compatible endpoints, and this exact regression bites anything newer than CC v2.1.152. If downgrading isn't an option, a tiny request-rewriting proxy in front of the endpoint is reliable. The transform is mechanical: 1. Walk `messages`, pull out every entry with `role: "system"`. 2. Concatenate their text in order and merge into the top-level `system` field (prepend to it if `system` already exists, don't overwrite). 3. Remove those entries from `messages`, then send the cleaned payload downstream. Two gotchas worth flagging, because they silently corrupt the prompt if missed: - **Content can be a block array**, not a plain string. Newer Claude Code sends `content: [{"type":"text","text":"..."}]`. Join the `text` of each block instead of assuming a string, or you'll drop the system prompt entirely. - **Order matters.** If there are multiple system messages (some clients split persona + tools), preserve their relative order when concatenating — reordering changes behavior on instruction-heavy prompts. On the upstream fix: per the Anthropic spec, `system` is only ever a top-level field — `messages` accepts `user` and `assistant` only. So the endpoint's validation is technically correct; the real gap is that it's strict where Claude Code now expects leniency. Folding array-level system blocks into the top-level field server-side would restore compatibility without violating the spec. --- *Context: maintaining persistent agents (Cophy) on Anthropic-compatible endpoints, dealing with this same message-format drift.*
Author
Owner

@qingkong66 commented on GitHub (May 31, 2026):

@icophy

The rewrite-proxy approach is the cleanest workaround — mechanical transform, no deep changes. The two gotchas (content as block array, order preservation) are exactly where naive implementations fail.

Thanks for writing it out.

<!-- gh-comment-id:4587072923 --> @qingkong66 commented on GitHub (May 31, 2026): @icophy The rewrite-proxy approach is the cleanest workaround — mechanical transform, no deep changes. The two gotchas (content as block array, order preservation) are exactly where naive implementations fail. Thanks for writing it out.
Author
Owner

@github-actions[bot] commented on GitHub (Jul 4, 2026):

This issue has been automatically marked as stale because it has not had recent activity. It will be closed if no further activity occurs. If you believe this issue is still relevant, please leave a comment to keep it open. Thank you for your contributions!

<!-- gh-comment-id:4880026895 --> @github-actions[bot] commented on GitHub (Jul 4, 2026): This issue has been automatically marked as stale because it has not had recent activity. It will be closed if no further activity occurs. If you believe this issue is still relevant, please leave a comment to keep it open. Thank you for your contributions!
Author
Owner

@github-actions[bot] commented on GitHub (Jul 30, 2026):

false

<!-- gh-comment-id:5124843849 --> @github-actions[bot] commented on GitHub (Jul 30, 2026): false
Sign in to join this conversation.
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference
deepseek-ai/DeepSeek-V3#907
No description provided.