[Bug]: Revert after an interrupted Claude run bricks the thread ("No message found with message.uuid"); the interrupted run is also dropped from context#25510
Before submitting
- I searched existing issues and did not find a duplicate.
- I included enough detail to reproduce or investigate the problem.
Area
apps/server
Steps to reproduce
- In a Claude (
claudeAgent) thread, complete a turn. Its last assistant message has UUIDH. - Send a prompt and revert it. T3 pins
nativeConversationHeadRef = H. - Send prompt P1 and stop it after Claude has produced at least one assistant message, so the run ends
interrupted. P1's last assistant message has UUIDX. - Send prompt P2.
- Revert P2.
- Send any message.
Expected behavior
- Step 4: P2 continues after P1, which the T3 timeline shows.
- Step 6: the thread resumes from the end of P1 and the message runs.
Actual behavior
At step 4, T3 opens the query with resumeSessionAt: H again. Claude appends P2 as a child of H, so the session transcript now has two sibling branches under H, and Claude answers P2 without P1 in its context. The UI does not show this.
At step 5, the revert targets P1's provider turn, whose nativeTurnRef is X, so T3 pins nativeConversationHeadRef = X.
At step 6 and on every later send, the query fails within about 1 s with error_during_execution:
| 1 | No message found with message.uuid of: <X> |
X is still in the transcript JSONL with an intact parent chain. The CLI resolves resumeSessionAt only against the chain that ends at the newest leaf, which is now P2's branch. Reverting again derives the same X, so the thread cannot be recovered from the UI.
query.open options from the provider event log of the affected thread (UUIDs shortened):
| Run | resumeSessionAt | Result |
|---|---|---|
| 22 | (live query, none) | reverted, pins 0d7d5eb7 (H) |
| 23 (P1) | 0d7d5eb7 | interrupted, last assistant message e4130616 (X) |
| 24 (P2) | 0d7d5eb7 | reverted, pins e4130616 |
| 25, 26, 27 | e4130616 | No message found with message.uuid of: e4130616-… |
In the transcript, run 23's and run 24's user messages both have parentUuid: 0d7d5eb7….
Cause
apps/server/src/orchestration-v2/Adapters/ClaudeAdapterV2.ts (main at 148d2fdc0e, same code in v0.1.2):
The pinned head is cleared only when a turn completes (L7266-L7268):
ts1 const clearConversationHead = 2 input.status === "completed" && 3 input.context.input.providerThread.nativeConversationHeadRef !== null; An
interruptedorfailedturn that wrote to the transcript leaves the head pointing before itself.openQuerypasses it asresumeSessionAton the next turn (L9641, L9739), so that turn branches off the old head and drops the interrupted turn.rollbackThreadpins the target turn'snativeTurnRef(resolveClaudeRollbackResumeSessionAt, applied at L10881-L10888) without checking that the UUID is on the chain the CLI will load. After (1), it is not.
The CLI behavior in (2) reproduces without T3 (Claude Code 2.1.310):
| 1 | S=$(uuidgen | tr A-Z a-z) |
| 2 | claude -p --session-id $S "Reply with just: one" # last assistant uuid A1 |
| 3 | claude -p --resume $S "Reply with just: two" # last assistant uuid A2 |
| 4 | claude -p --resume $S --resume-session-at $A1 "Reply with just: three" |
| 5 | # three |
| 6 | claude -p --resume $S --resume-session-at $A2 "Reply with just: four" |
| 7 | # No message found with message.uuid of: <A2> (exit 1; A2 is still in the JSONL) |
Possible fixes
- Clear
nativeConversationHeadRefwhen an interrupted or failed turn has written to the transcript (for example whennativeMessageCursor !== null), not only oncompleted. The next resume then starts from the newest leaf, which matches the T3 timeline. Fixing this alone prevents the brick in the steps above. - Before pinning a rollback anchor, check that it is an ancestor of the transcript's newest leaf. If it is not, fork or truncate at the target, or refuse the revert.
- Let the user recover a thread when the CLI returns this error, as proposed in #17423.
Related: #17423 (same error after reverting past a compaction boundary), #21128 (same error from a subagent UUID used as the turn cursor, closed).
Impact
Blocks work completely
Version or commit
T3 Code (Beta) 0.1.2, server 0.1.2. The relevant code is unchanged on main 148d2fdc0e.
Environment
macOS (Darwin 25.6.0), Claude Code CLI 2.1.310, claudeAgent provider, claude-opus-5-5