Session resume after 403 retry breaks parentUuid chain, losing entire conversation history
Bug Description
When an API 403 error triggers automatic retries, the retry mechanism re-sends the user message with an incorrect parentUuid, pointing to a subagent's progress message instead of the main conversation chain. Upon session resume, the conversation tree is rebuilt from this broken branch, causing all prior conversation history to be permanently lost from context.
This is not context compression — the JSONL file retains the full history, but the model receives none of it because the parent chain is severed.
Reproduction Steps
- Have a long-running conversation session with subagents (progress messages present)
- Send a message that triggers a 403 API error (
{"error":{"type":"forbidden","message":"Request not allowed"}}) - Claude Code automatically retries the same message multiple times
- Close the terminal window and reopen / resume the session
- The model now only sees the last message — all prior history is gone
Root Cause Analysis
From the JSONL file (a6de1f0c-178d-4085-9fd0-0f7abf13cc70.jsonl, ~53K lines):
First send (correct parent):
L53699 [system/turn_duration] uuid=9ef20ec5-101..
L53701 [user] parentUuid=9ef20ec5-101.. uuid=de92f26a-e76.. ← correct, points to main chain
L53702 [assistant] 403 error
Retries (broken parent):
L53703-53734 [progress] ← subagent progress messages, chain ends at uuid=558d5e73-82e..
L53736 [user] parentUuid=558d5e73-82e.. ← WRONG! Points to progress msg, not main chain
L53737 [assistant] 403 error
...
L53745 [user] parentUuid=558d5e73-82e.. ← same broken parent, retry #3
L53746 [assistant] 403 error
...
L53754 [user] parentUuid=558d5e73-82e.. ← retry #4, finally succeeds
L53756 [assistant] normal response
The retries all use parentUuid=558d5e73-82e.. which is a progress message from a subagent sidechain, not the main conversation's turn_duration system message (9ef20ec5-101..).
When the session is resumed, the conversation tree is walked from L53754 backwards via parentUuid, which goes into the progress sidechain and never reaches the actual conversation history.
Expected Behavior
- Retries after 403 should preserve the original
parentUuidfrom the first (failed) attempt - The parent should always point to the main conversation chain, never to progress/sidechain messages
- Session resume should not lose conversation history due to retry-induced parent chain corruption
Impact
- Severity: Data loss — entire conversation context silently disappears
- User-visible: After resume, the model has no memory of prior conversation (not compression, complete loss)
- JSONL intact: The full history exists in the JSONL file but is unreachable via the broken parent chain
Environment
- Claude Code CLI (latest as of 2026-03-22)
- Model: claude-opus-4-6
- OS: Arch Linux
- Terminal: Ghostty
This issue has 7 comments on GitHub. Read the full discussion on GitHub ↗