[BUG] API returns the same `message.id` across multiple sequential responses under load (silent corruption, no error)
Preflight
- This is a single bug report.
- Found by post-hoc audit of the session transcript JSONL; evidence below is from that transcript.
What's Wrong?
During a period of server load, the Anthropic API returned the same message.id
(msg_018fjzPAQ4xzfrCdBQsoL1En) across six distinct, sequential assistant responses.
Each was a separate API call (distinct tool_use IDs; each consumed the previous call's
tool result), so this is not the normal case of one response emitting multiple content
blocks. message.id is expected to be unique per response.
The client accepted each duplicate-ID response as valid and executed its tool call. The
model lost track of what it had already read and fell into a re-read loop that ended the
session with no work produced. A clean overload error (429/529) would have let the client
back off; instead the API returned malformed-but-parseable data — silent corruption rather
than a clean failure.
Environment
- Claude Code 2.1.156 (desktop)
- Model: claude-opus-4-8
- Window: 2026-05-31, 19:09:23–19:09:36 UTC (≈13 seconds)
Evidence
In the transcript, msg_018fjzPAQ4xzfrCdBQsoL1En is carried by six sequential assistant
responses, each separated by an executed tool call and its result:
| # | time (UTC) | tool call | result |
|---|-----------|-----------|--------|
| 1 | 19:09:23 | "plan approved" text + mark_chapter | ok |
| 2 | 19:09:26 | Read file A | success |
| 3 | 19:09:31 | Read file B | success |
| 4 | 19:09:32 | Read file A again | "Wasted call — file unchanged…" |
| 5 | 19:09:34 | Read file B again | "Wasted call — file unchanged…" |
| 6 | 19:09:36 | Read file A again | (session ends) |
Each response has a distinct parentUuid pointing at the preceding tool result (proving
they are sequential responses, not parallel content blocks of one generation) and a
distinct tool_use id (proving distinct generations). Only the message.id is shared.
Expected vs Actual
- Expected: unique
message.idper response; under load, a clean retryable error. - Actual: one
message.idreused across six sequential responses; no error surfaced.
Asks
- Confirm whether duplicate
message.idemission is reproducible under load; treat it as a
server-side invariant violation (a message.id must be unique per response).
- Add a client-side defense: reject a response whose
message.idequals the immediately
preceding response's, rather than executing its tool call.
Related issues reviewed — why this is distinct
- #20640 (closed) — also a
message.idcollision, but client-side: a reference-aliasing
bug created duplicate message.id appearances locally, which the next call rejected with a
- Here the server emits the same id across six responses, accepted without error.
- #59520 (open) — after a 429, every retry fails 400 on
previous_message_id(the client
sending a bad id). That fails loud; this fails silent, with the server reusing a real id.
- #6805 (closed) / #22658 (closed) — both show "same
message.idon multiple records,"
but that is expected there (one response split into content blocks; parallel-agent copies,
which share the same tool_use id). Here the responses are sequential, with distinct
parentUuids and distinct tool_use ids.
- #12303 (closed) — two API requests per user message via
stop_reason: nullcontinuation
(two distinct requestIds) — a client continuation artifact, not server id reuse.
- #53669, #52773 (closed) — "duplicate response" reports with absent/different
mechanism (vague; TUI re-rendering).
_(A companion report covers the client-side absence of a circuit breaker on the resulting
re-read loop; filed separately.)_
This issue has 2 comments on GitHub. Read the full discussion on GitHub ↗