[BUG] API returns the same `message.id` across multiple sequential responses under load (silent corruption, no error)

Status Open
Reported on v2.1.156
Maintainer reply None cached
Activity 4 comments · opened Jun 2, 2026

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.id per response; under load, a clean retryable error.
  • Actual: one message.id reused across six sequential responses; no error surfaced.

Asks

  1. Confirm whether duplicate message.id emission is reproducible under load; treat it as a

server-side invariant violation (a message.id must be unique per response).

  1. Add a client-side defense: reject a response whose message.id equals the immediately

preceding response's, rather than executing its tool call.

Related issues reviewed — why this is distinct

  • #20640 (closed) — also a message.id collision, but client-side: a reference-aliasing

bug created duplicate message.id appearances locally, which the next call rejected with a

  1. 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.id on 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: null continuation

(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.)_

View original on GitHub ↗

4 Comments

blwfish · 2 months ago

Related reports from the same session audit:

  • #64882 — the re-read loop this corruption triggered (the client accepted each duplicate-message.id response and dispatched its tool call, driving that loop).
  • #64881 — a subagent path-fabrication issue from the same session.

The client-side circuit-breaker gap (no cap on repeated identical failing tool calls) is being raised on the existing #38405.

blwfish · 2 months ago

Periodic verification — June 2026

Checked against Claude Code v2.1.185 (latest release as of 2026-06-21).

Reproduction test: ℹ️ Not testable this run — reproducing a duplicate/shared message.id requires concurrent API traffic under load, which can't be deterministically triggered from a single session.

Release notes through v2.1.185: no mention of a fix for duplicate message.id values under load.

This comment is posted automatically (~every run) to prevent stale-bot closure (threshold: 28 days inactive). Reporter (@blwfish) will close upon confirming resolved.

blwfish · 29 days ago

Periodic verification — August 2026

Checked against Claude Code v2.1.220 (latest release as of 2026-08-01).

Reproduction test: ℹ️ Not testable this run — duplicate message.id emission is a server-side, load-dependent condition with no deterministic client-side trigger. It has not recurred in captured telemetry since the original report, but absence under normal load is not evidence of a fix.

Release notes through v2.1.220: no mention of a fix.

Note: this issue was auto-labeled stale on 2026-07-19 with no maintainer response at any point.

This comment is posted automatically every ~10-20 days to prevent stale-bot closure. Reporter (@blwfish) will close upon confirming resolved.

blwfish · 9 days ago

Periodic verification — August 2026

Checked against Claude Code v2.1.238 (latest release as of 2026-08-21).

Reproduction test: ℹ️ Not reproduced in this window — scanned 14 days of local transcripts (31,762 assistant records, 13,663 distinct message.id values) for a message.id shared across separate API responses.

Every candidate resolved to a known non-bug artifact rather than the reported defect:

  • One API response with parallel tool_use blocks is written as N separate JSONL lines that all carry the same message.id and the same usage payload, with each block's tool_result interleaved as its call returns. Looks like duplication; isn't.
  • 3 groups were literal re-appended JSONL lines (identical record_uuid, identical timestamp) — a transcript-writing artifact, not distinct API responses.

This is a weak negative, not a confirmed fix: the original report was load-dependent, and this window contained no comparable load spike. Leaving open.

Release notes through v2.1.238: no mention of a fix.

This comment is posted automatically every ~20 days to prevent stale-bot closure (threshold: 28 days). Reporter (@blwfish) will close upon confirming resolved.