anthropics / anthropics/claude-code

[BUG] Regression in 2.1.266: client emits system message at an invalid position → API 400 "role 'system' must precede an 'assistant' message or end the array"

Đang mở
#94,294 1 bình luận 0 reaction 0 người được giao Xem trên GitHub
area:core bug platform:macos regression
Ngôn ngữ chính
Python
Star
145k
Fork
23.1k
Chỉ số merge pull request
Chỉ số pull request đang chờ

Mô tả

### Preflight Checklist

- [x] I have searched [existing issues](https://github.com/anthropics/claude-code/issues?q=is%3Aissue%20state%3Aopen%20label%3Abug) and this hasn't been reported yet
- [x] This is a single bug report (please file separate reports for different bugs)
- [x] I am using the latest version of Claude Code

### What's Wrong?

Since v2.1.266, Claude Code intermittently builds a request whose `messages` array contains a `system`-role entry in a position the Messages API rejects. The turn fails with:

API Error: 400 messages.N: role 'system' must precede an 'assistant' message or end the array; the directive-only form (content: [] with output_config) is accepted at any position

N varies (7, 13, 16, 19, 138, 151). There is no way to avoid or recover from it other than retrying the turn.

This is a clean regression. I scanned every session transcript in ~/.claude/projects/**/*.jsonl and correlated the error against the `version` field on each entry:

- 28 distinct versions used before the regression, from 2.1.142 (2026-05-26) through 2.1.260 (2026-09-11): zero occurrences
- First occurrence: 2026-09-11 09:24:56 on 2.1.266 — the first day 2.1.266 appears in my logs
- Still occurring on 2.1.268 and 2.1.270 (2026-09-14)

Impact so far: ~48 failed turns across 14 sessions in 3 separate projects.

Possible lead: a large share of failures are preceded within a few transcript entries by client-generated system-subtype records — most often `system/stop_hook_summary`, also `system/turn_duration` and `system/away_summary`. Notably `stop_hook_summary` entries appear even though I have no hooks configured. That suggests these internal system records may be serialized into the outgoing messages array without the position check the API enforces. I can't confirm that from transcripts alone — it's a lead, not a diagnosis. Also common nearby: `queue-operation` (queued user messages) and `attachment` / `file-history-snapshot` records, so an interrupted or queued turn may be part of the trigger.

No deterministic repro — it appears mid-session during ordinary use across unrelated projects, roughly once every few dozen turns, not tied to any one project, skill, or tool. Retrying usually succeeds.

### What Should Happen?

The client should never place a `system`-role entry in a position the Messages API rejects — or should use the directive-only form (content: [] with output_config), which is valid at any position. The turn should complete normally instead of 400ing and being lost.

### Error Messages/Logs

```shell
API Error: 400 messages.7: role 'system' must precede an 'assistant' message or end the array; the directive-only form (content: [] with output_config) is accepted at any position

Observed occurrences (timestamp, version):
2026-09-11T09:24:56 2.1.266 <-- first
2026-09-11T09:25:51 2.1.266
2026-09-11T09:26:39 2.1.266
2026-09-11T09:27:07 2.1.266
2026-09-11T09:28:59 2.1.266
2026-09-11T09:34:51 2.1.266
2026-09-11T09:55:08 2.1.266
2026-09-11T12:31:52 2.1.266
2026-09-11T12:32:23 2.1.266
2026-09-11T12:39:19 2.1.266
2026-09-11T13:50:36 2.1.266
2026-09-11T14:10:46 2.1.266
2026-09-11T14:22:07 2.1.268
2026-09-11T14:23:28 2.1.266
2026-09-11T14:41:14 2.1.266
2026-09-14T08:09:19 2.1.266
2026-09-14T08:36:02 2.1.266
2026-09-14T08:54:23 2.1.266
2026-09-14T12:35:14 2.1.270
2026-09-14T13:30:31 2.1.266
2026-09-14T13:30:50 2.1.270
2026-09-14T13:35:07 2.1.266
2026-09-14T13:37:19 2.1.266
2026-09-14T13:37:28 2.1.266
2026-09-14T13:39:56 2.1.266
2026-09-14T13:40:21 2.1.266
```

### Steps to Reproduce

No deterministic repro — the failure appears mid-session during ordinary use, roughly once every few dozen turns, across unrelated projects, and is not tied to any one project, skill, or tool. Retrying the turn usually succeeds. What I can give you is an exact way to observe it and confirm the version boundary from any affected machine's own transcripts.

To observe:
1. Install 2.1.266 or later (reproduced on 2.1.266, 2.1.268, 2.1.270).
2. Use Claude Code in the desktop app normally — multi-turn sessions with tool use, queued messages, and interruptions. No special configuration; I have no hooks configured (settings.json contains only permissions, theme, skipWorkflowUsageWarning).
3. Within a few dozen turns a turn fails with:
API Error: 400 messages.N: role 'system' must precede an 'assistant' message or end the array; the directive-only form (content: [] with output_config) is accepted at any position

To confirm the version boundary from transcripts (this is how I established it):

cd ~/.claude/projects && find . -name '*.jsonl' -print0 | xargs -0 grep -h "must precede an" \
| python3 -c "
import sys,json
for l in sys.stdin:
try: d=json.loads(l)
except: continue
print(d.get('timestamp','?')[:19], d.get('version','?'))
" | sort

On my machine this returns zero rows for all 28 versions from 2.1.142 (2026-05-26) through 2.1.260, and the first row is 2026-09-11T09:24:56 on 2.1.266 — the first day 2.1.266 appears in my logs.

Scope check — the failures are on main-thread interactive turns, not subagents. Every affected transcript entry has userType "external" and isSidechain false; zero sidechain occurrences across 14 sessions in 3 projects.

I can't produce a minimal code example because no file or code triggers it — the malformed request is built by the client, and nothing in the user's project is involved. If it helps, I can supply the raw transcript entries around a failure, though I'd need to redact work content first.

### Claude Model

Opus

### Is this a regression?

Yes, this worked in a previous version

### Last Working Version

_No response_

### Claude Code Version

2.1.270

### Platform

Anthropic API

### Operating System

macOS

### Terminal/Shell

Terminal.app (macOS)

### Additional Information

Version reporting caveat: `claude --version` returns 2.1.270, but the desktop app pins a bundled CLI per session. My current session runs 2.1.266 (CLAUDE_CODE_EXECPATH=.../Claude/claude-code/2.1.266/claude.app/..., AI_AGENT=claude-code_2-1-266_agent), which is why failures dated 2026-09-14 still log version 2.1.266 alongside ones logging 2.1.270. Updating the CLI may not move existing sessions off the affected build.

Scope: ~48 failed turns across 14 sessions in 3 projects since 2026-09-11. All on main-thread interactive turns — every affected entry has userType "external" and isSidechain false, zero sidechain occurrences.

No hooks configured. settings.json contains only permissions, theme, skipWorkflowUsageWarning.

One lead, unconfirmed: many failures are preceded within a few transcript entries by client-generated system-subtype records — most often system/stop_hook_summary, also system/turn_duration and system/away_summary. stop_hook_summary appears despite no hooks being configured. Possibly these internal system records are serialized into the outgoing messages array without the position check the API enforces. Also frequently nearby: queue-operation (queued user messages) and attachment / file-history-snapshot records.

Hướng dẫn đóng góp

Chưa lập chỉ mục được hướng dẫn đóng góp cho kho mã nguồn này

Đánh giá

Issue này chưa được đánh giá.

Nhận issue mới trong hộp thư của bạn

Bản tóm tắt ngắn những issue GitHub phù hợp với người mới.