API-error retry bookkeeping orphans the successful turn from the parentUuid chain; --resume then silently drops it from context

Resolved 💬 3 comments Opened Jun 10, 2026 by graehl Closed Jun 13, 2026

Environment

  • Claude Code CLI 2.1.170, Linux (RHEL 8)
  • Session JSONL produced by Claude Code on 2026-06-10

Summary

When an API call fails mid-turn (e.g. a 502) and the automatic retry succeeds, the system/api_error bookkeeping row is not written at error time — it is buffered and flushed at the next user turn, and that next user row is parented to the api_error row instead of the real conversation tip. This orphans the entire successful retry output (the turn the user just read) onto a childless parentUuid branch.

claude --resume rebuilds model context by walking parentUuid from the tip, so after a resume the session has permanently lost that turn: the assistant cannot recall work it completed and the user read. Verified end-to-end below.

Evidence (session JSONL, 0-based lines, times UTC)

| line | type | uuid → parentUuid | timestamp |
|---|---|---|---|
| 183 | user | 746766dd954c3b08 | 00:28:26.196 |
| 184 | attachment (date_change) | 2bfe3cdd746766dd | 00:28:26.196 |
| 185–198 | assistant/user (full turn: thinking, tool_use/tool_result pairs, final text) | 7fbf8c932bfe3cdd, … chain … → 379dabdb | 00:28:56 – 00:29:28 |
| 199–200 | queue-operation enqueue/dequeue | — | 00:29:38.370 |
| 201 | system/api_error (retryAttempt: 1, Cloudflare 502) | 175c3fca2bfe3cdd | 00:28:26.415 (out of file order) |
| 202 | user | 95157e48175c3fca | 00:29:38.373 |

Reconstruction:

  1. 00:28:26.196 — user turn delivered; the attachment row (184) is the leaf when the API call starts.
  2. 00:28:26.415 — attempt 1 fails with a 502. The api_error row captures this timestamp and parent (= the leaf at error time), but is not written to the file yet.
  3. 00:28:56–00:29:28 — the retry succeeds; the full turn output is appended normally, chaining from 184. Tip on disk: line 198.
  4. 00:29:38 — next user message: the buffered api_error row is finally flushed (line 201, error-time timestamp, hence out of order), and the new user row (202) is parented to it, not to the tip at 198.
  5. Everything afterward descends from the api_error row. Lines 185–198 have no descendants — a "dead branch" that is actually completed, displayed conversation.

Demonstrated consequence: resume context loss

Probe: claude -p --resume <session> --fork-session with all retrieval tools disallowed (--disallowedTools Bash Read Grep Glob ...), asked three questions:

  • two facts that exist only in the orphaned segment (the opening words of an assistant status message there, and the exact temp-file path used in a command there);
  • one control fact from the live branch seconds later (same vintage).

Result: the control came back verbatim-accurate, and the model also quoted exact mechanical details (temp-file paths) from other live turns of the same age and depth — but both orphaned-segment facts were reported absent, with the model itself noting the amend turn "is exactly the turn that's missing from my context." Token usage shows ~367k input tokens loaded into a 1M-context model, so this is not compaction or truncation: the segment is excluded by the chain walk.

Before the resume, the in-process model clearly had the content (the conversation continued from it normally). It is only lost when context is rebuilt from the file.

Expected behavior

  • The next user turn after a retried-and-succeeded API call should be parented to the real conversation tip, not to the deferred error bookkeeping row.
  • Alternatively/additionally, resume's chain walk should not drop a completed sibling branch that the error row orphaned.

Impact

  • --resume (and presumably fork/compact flows that walk parentUuid) silently lose completed work after any mid-turn API error + successful retry — a common pattern during provider incidents.
  • Transcript consumers that follow parentUuid see the successful turn as an abandoned dead branch.

Happy to share the full session JSONL or the probe transcript on request.

View original on GitHub ↗

This issue has 3 comments on GitHub. Read the full discussion on GitHub ↗