[BUG] "Can't rewind to this message" for every target older than the newest mid-turn queued message — `queued_command` uuid rewrite breaks the Desktop active-chain walk

Status Open
Reported on v2.1.229
Maintainer reply None cached
Activity 0 comments · opened Aug 14, 2026

Preflight Checklist

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

What's Wrong?

In the Desktop app, Rewind refuses every message older than the newest mid-turn queued message in the session. The picker shows the target and its rewind point resolves, but the active-chain membership check rejects it, so the UI says "Can't rewind to this message" and main.log gets not on active chain.

The cause is visible in the main-process bundle (Desktop 1.30096.1, .vite/build/index.chunk-B9EbikZf.js and index2.chunk-B98k4ogs.js):

  1. loadRawChainEntries maps each transcript line to a slim chain entry. For attachments with attachment.type: "queued_command" (the storage shape of a message typed while Claude is working) it replaces the entry's uuid with attachment.source_uuid and its type with user. The attachment's original uuid is now absent from the entry list
  2. The next transcript line's parentUuid still names that original uuid. The active-chain builder looks the parent up in a map keyed by the rewritten uuids, misses, and falls back to a timestamp repair that only accepts an unvisited entry up to 5 s older (ni=5e3). A queued message is normally picked up well over 5 s after it was typed, so the repair finds nothing and the walk stops
  3. The "active chain" therefore ends at the newest queued message instead of the session root. Every target below it fails the membership test and is refused, with telemetry desktop_ccd_session_rewind_rejected_dead_branch

Replaying the app's exact walk against an affected session's transcript reproduces the logged numbers precisely: 966 chain entries, walk stops at the child of the newest queued_command attachment after 94 nodes (the logged chain size 94/966), nearest repair candidate 38.9 s older — outside the 5 s window. The identical walk with original uuids kept reaches the session root with 959 of 966 entries on chain, the refused target among them.

What Should Happen?

Rewind should reach every checkpoint on the real chain. The transcript on disk is intact — the rewritten entry still carries the attachment's parentUuid, and the CLI resumes the same file fine — only the map key changes at load time, so this looks fixable entirely inside the chain builder.

Error Messages/Logs

2026-08-14 11:16:02 [info] LocalSessions.rewindV2: sessionId=local_f7fe085f… target=9184ecf6…
2026-08-14 11:16:02 [info] [Rewind] target=9184ecf6… → assistantUuid=ed5365a4… not on active chain for local_f7fe085f… (chain size 94/966)

From ~/Library/Application Support/Claude/Logs/main.log — four identical refusals across two minutes of retries. The session's transcript at that moment held exactly 966 uuid entries, 60 attachments, 5 of them queued_command with commandMode: "prompt".

Steps to Reproduce

  1. In the Desktop app, send a prompt that keeps Claude busy for a couple of minutes
  2. While it works, send another message. It lands in ~/.claude/projects/<project>/<sessionId>.jsonl as {"type":"attachment","attachment":{"type":"queued_command","commandMode":"prompt","source_uuid":"…"}}, and the following line's parentUuid points at the attachment's own uuid
  3. Let the turn finish, with the queued message picked up more than 5 s after it was typed (the usual case)
  4. Open Rewind and pick any message older than the queued one — refused, while targets in the stretch above it still work

I haven't run these four steps from scratch in a fresh session — the replay above is the deterministic form of the same evidence.

Claude Model

Not sure / Multiple models

Is this a regression?

I don't know

Last Working Version

_No response_

Claude Code Version

2.1.229 (Claude Code), bundled in Claude Desktop 1.30096.1

Platform

Anthropic API

Operating System

macOS

Terminal/Shell

Other

Additional Information

Environment: the Claude Desktop app on macOS 26.5.1, Apple Silicon.

Related but different bugs: #59697 (constant chain size 2/N on conversation-only sessions, closed) and #76114 (SSH sessions, no file-history snapshots) look like other roads to the same refusal message, and #83103 is the same queued_command storage shape breaking transcript rendering instead of rewind, while #85510 pairs the same two features the other way round (Rewind dropping queued messages). Unlike #59697 the chain here is large and grows with the session — it just never reaches past the newest queued message.

Mid-turn messages are routine in long sessions, so in practice this caps Rewind at "since the last queued message" exactly for the sessions that need it most. The refused stretch is not dead — truncating the transcript at the refused target (app quit) and reopening resumes exactly there. This membership check is all that stands between the user and that history.

View original on GitHub ↗