claude-code - 💡(How to fix) Fix [BUG] claude --resume picks a stale branch on forked session JSONL, compounds on every resume on 2.1.108 [1 participants]

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…
GitHub stats
anthropics/claude-code#48270Fetched 2026-04-16 07:04:36
View on GitHub
Comments
0
Participants
1
Timeline
3
Reactions
0
Participants
Timeline (top)
labeled ×3

Error Message

Error Messages/Logs

Fix Action

Fix / Workaround

Current workaround

RAW_BUFFERClick to expand / collapse

Preflight Checklist

  • I have searched existing issues and this hasn't been reported yet
  • This is a single bug report (please file separate reports for different bugs)
  • I am using the latest version of Claude Code

What's Wrong?

Summary

On a session JSONL that has forked into multiple branches (e.g. due to concurrent claude --resume processes on the same sessionId, or auto-continue tooling writing to old parents), claude --resume <sessionId> consistently anchors to a stale branch — even when a much newer / much longer branch exists. Each subsequent resume extends the stale branch further, making recovery progressively harder. The picker's choice doesn't match timestamps, chain length, or the JSONL's own last-prompt metadata entry.

Environment

  • Claude Code version: 2.1.108
  • OS: Linux (Arch)
  • Shell: bash

Actual behavior

On a real session (f3c03304-... in our repo) with:

  • 3356 entries / 375 leaves in the JSONL tree
  • Main conversation spine: chain length 1243, tip ts 2026-04-15T02:34:56Z, leaf uuid 93bb8cd9-...
  • Most-recent meaningful branch: chain length 395, tip ts 2026-04-15T03:00:35Z, leaf uuid 88e505f0-...
  • last-prompt metadata entry: {"type":"last-prompt","lastPrompt":"you fix it.","sessionId":"f3c03304-..."} — points to a user message at ts 2026-04-14T04:57:20Z

claude --resume f3c03304-... consistently picks leaf 4633e2a1-...:

  • chain length: 256
  • tip ts: 2026-04-15T03:35:15Z (the timestamp is recent but it's just an auto-continue ping)
  • walking root→leaf, substantive conversation ends at 2026-04-13T05:49 — two days old
  • the leaf is a descendant of a 2026-04-13 user message "continue, had an interuption"

So the picker ignores:

  • the 1243-node main spine (much longer chain, similar tip ts)
  • the 395-node meaningful branch (newer tip)
  • the last-prompt entry (points to yet a third node from 04-14)

The user sees 2-day-old content on resume. Every message they type gets appended as a child of that stale leaf, creating new short forks off the old anchor. Re-resuming the session causes the fragmentation to compound — after several cycles the tree accumulates hundreds of short branches, none connected to the real conversation tip.

Expected behavior

claude --resume <sessionId> should resume to the leaf of the branch representing the user's actual conversation tip — i.e. either (a) the longest root-to-leaf chain, (b) the leaf with the latest substantive (non-auto-continue) user message, or (c) a branch pointer that's reliably kept in sync when the user sends new messages. Whatever algorithm is chosen should be deterministic and robust to concurrent writes.

Reproduction ingredients (not all needed — any combination that produces a forked tree seems sufficient):

  1. Long session that has passed at least one auto-compaction boundary.
  2. Multiple claude --resume <sameSessionId> processes running concurrently (this was accidentally triggered by a workspace-restore feature in a third-party GUI app — 12 concurrent CLIs resuming the same session).
  3. External tooling (e.g. a /loop watcher, keep-alive prompt, or workflow script) that sends a user message to a resumed session when the real user is idle.
  4. Any of the above interleaving with real user messages on a different branch.

Evidence / diagnostic

  • JSONL path: ~/.claude/projects/<encoded-cwd>/<sessionId>.jsonl
  • 375 leaves in the tree, with a clear main spine
  • The three pointers (last-prompt, the picker's chosen leaf, the human-meaningful tip) all disagree
  • Once the picker is anchored wrong, every resume amplifies the problem

Fix directions (suggestions)

  • Make the leaf picker prefer chain length from root over timestamp, or combine the two (e.g., latest tip among leaves with chain length ≥ some fraction of the max).
  • Ensure there's exactly one writable CLI per sessionId at a time (file lock), or add a conflict-resolution pass on resume that repairs the tree.
  • Keep last-prompt (or an equivalent leaf pointer) updated atomically after each user input, and use it as the canonical resume anchor.
  • Expose a --resume-leaf <uuid> flag so users can manually specify which leaf to resume from when auto-picking gets it wrong.

Current workaround

Manually rewrite the JSONL to contain only the desired linear chain (backing up the original), so the picker has no branches to disambiguate. Not pleasant, and non-obvious.

What Should Happen?

.

Error Messages/Logs

Steps to Reproduce

.

Claude Model

None

Is this a regression?

I don't know

Last Working Version

No response

Claude Code Version

2.1.108

Platform

Anthropic API

Operating System

Other Linux

Terminal/Shell

Xterm

Additional Information

No response

extent analysis

TL;DR

The issue can be fixed by modifying the leaf picker to prefer chain length from root over timestamp or combining the two, and ensuring that there's exactly one writable CLI per sessionId at a time.

Guidance

  • Modify the leaf picker algorithm to prioritize chain length over timestamp, or combine the two factors to determine the most suitable leaf for resuming a session.
  • Implement a file lock or conflict-resolution mechanism to prevent multiple CLIs from writing to the same sessionId simultaneously, which can cause the tree to become fragmented.
  • Update the last-prompt metadata entry atomically after each user input to ensure it points to the correct leaf, and use it as the canonical resume anchor.
  • Consider adding a --resume-leaf flag to allow users to manually specify the leaf to resume from when the auto-picking mechanism fails.

Example

No code snippet is provided as the issue does not contain sufficient information about the implementation details of the leaf picker algorithm or the JSONL file structure.

Notes

The provided fix directions are suggestions based on the issue description, and the actual implementation may vary depending on the specific requirements and constraints of the Claude Code project.

Recommendation

Apply a workaround by modifying the leaf picker algorithm to prioritize chain length over timestamp, and ensure that there's exactly one writable CLI per sessionId at a time, as this is the most likely cause of the issue and can be implemented without requiring significant changes to the existing codebase.

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