claude-code - 💡(How to fix) Fix [BUG] --resume reconstructs a stale fork as the live conversation: an orphaned tool-permission grafted onto an old tool_use wins max-timestamp leaf selection (v2.1.150)

Official PRs (…)
ON THIS PAGE

Recommended Tools

×6

Utilities matched from this issue’s tags and category — try them while you read without losing context.

GitHub issue graph ai analysis

Paste a GitHub issue URL. We fetch that issue, discover linked issues from bodies/comments/timeline, collect linked pull requests, and produce a structured English report.

The report is written in English Markdown for sharing and archival.

Helpful · Quick feedback

Loading…

On --resume, a long-running session was reconstructed from a stale early branch instead of its actual latest thread — silently, no error. The parentUuid chain was fully intact (no dangling references), so this is not a dropped-history or chain-break problem — the failure is in leaf selection. An orphaned tool-permission, resolved at startup, grafted a new branch onto a days-old tool_use, and that graft carried the newest timestamps — so the loader selected it as the "live" conversation.

Error Message

instead of its actual latest thread — silently, no error. The parentUuid chain was

  • v2.1.116 (dead-fork handling / silent-empty→error reporting) doesn't apply — the result

Root Cause

On --resume, a long-running session was reconstructed from a stale early branch instead of its actual latest thread — silently, no error. The parentUuid chain was fully intact (no dangling references), so this is not a dropped-history or chain-break problem — the failure is in leaf selection. An orphaned tool-permission, resolved at startup, grafted a new branch onto a days-old tool_use, and that graft carried the newest timestamps — so the loader selected it as the "live" conversation.

RAW_BUFFERClick to expand / collapse

Summary

On --resume, a long-running session was reconstructed from a stale early branch instead of its actual latest thread — silently, no error. The parentUuid chain was fully intact (no dangling references), so this is not a dropped-history or chain-break problem — the failure is in leaf selection. An orphaned tool-permission, resolved at startup, grafted a new branch onto a days-old tool_use, and that graft carried the newest timestamps — so the loader selected it as the "live" conversation.

Environment

  • Claude Code v2.1.150, Linux, Opus 4.7 (1M context). Remote-control/bridge active.

Mechanism (verified against the session JSONL + minified cli)

  1. Resume selects the leaf with the latest timestamp, then walks parentUuid to root (ve7S5H).
  2. The session contained an un-acted tool-permission from days earlier — a permission prompt (a Skill invocation) that was never approved/denied; the user moved on and the tool-call was abandoned (left in the tree as a dead branch).
  3. On resume after a restart, an orphaned permission response for that old tool_use's id was drained at startup (handleOrphanedPermissionResponse + drainCommandQueue prioritization) and written as a child of the ancient tool_use — grafting a fresh branch onto it.
  4. That graft, plus everything typed afterward, became the newest-timestamped leaves. Leaf selection therefore picked the graft branch and walked it to its old root, reconstructing the wrong conversation and bypassing the actual latest thread. Nothing was dropped — the real conversation was intact on disk, just on an unselected branch.

Why the v2.1.101 fix doesn't catch it

  • The v2.1.101 fix ("loader anchored on a dead-end branch instead of the live conversation") is defeated here: the graft makes a stale-rooted branch carry the newest timestamps, so the loader treats the dead fork as live.
  • v2.1.116 (dead-fork handling / silent-empty→error reporting) doesn't apply — the result isn't an empty load; a valid but wrong branch is loaded.

Reproducibility

This is a mechanism report, not a deterministic repro. The triggering permission response is not persisted in the JSONL (no control_response entries; the bridge-session lastSequenceNum stays 0). The delivery path is almost certainly the remote-control/cloud bridge re-delivering the un-acted permission on reconnect, but that is inferred — only the grafted result is written to the transcript. The graft, its parentage onto the old tool_use, and the timestamp ordering are all verifiable in the JSONL.

Suggested fix angles

  1. Drop orphaned permissions whose tool_use is not on the current live-leaf chain (the "no matching tool_use" drop path already exists — extend it to "matching but off-active-thread").
  2. Ensure dead-fork pruning runs before leaf selection, so a stale-rooted graft can't win the max-timestamp race.
  3. Prefer the recorded session leaf (last-prompt / currentSessionLeafUuid) over a leaf created by an orphaned-permission drain at startup.

— Written by Claude Code (Opus 4.7) on behalf of @0reo

Vote matrix · Quick signals

Works
Did the solution work? Tap to confirm.
Easy Fix
Was it a quick fix?
Time Saver
Did it save you time?
Blocking
Was it severely blocking?
Common Issue
Are others likely hitting this too?
Flaky / Intermittent
Is it intermittent?
Verified / Reproducible
Can you reproduce it reliably?
Loading…

Still need to ship something?

×6

Another batch ranked right after the header list — different links, same matching logic.

Back to top recommendations

TRENDING