Skip to content

[Bug]: Reverting past a Claude compaction breaks the thread: every send fails with "No message found with message.uuid" #17423

Open

Description

@elmarbeckmann

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

  1. In a Claude (claudeAgent) thread, finish a few turns. Call the last completed turn N. Its final assistant message has UUID X.
  2. Send another prompt. During that run, a manual /compact writes a compact_boundary to the session transcript (trigger: "manual", with preservedSegment / preservedMessages). Let the run continue after the compaction.
  3. Revert the thread to the end of turn N, so that the runs after N are rolled_back.
  4. Send any new message.

Expected behavior

The thread resumes from the end of turn N and the new message runs.

Actual behavior

The revert succeeds. After it, every send fails within about 1 s:

Provider error: No message found with message.uuid of: <X>

The thread stays failed, and every later message gives the same error. You cannot recover the thread from the UI.

The cause, from the session transcript (~/.claude/projects/<project>/<session>.jsonl):

  • Line 547: assistant message X (end of turn N). Line 548: its stop_hook_summary.
  • Line 594: the compact_boundary from the rolled-back run (parentUuid: null, logicalParentUuid points to the end of that run).

T3 resumes with resumeSessionAt: X. The CLI loads only the chain after the newest compact_boundary, so X is not in the loaded messages and the resume fails. The rollback leaves the transcript as it is, which makes the resume point unreachable.

Workaround: Truncate the transcript after line 548, which removes the rolled-back runs and the boundary. The thread then resumes normally.

Related but different: #13638. There, the rewind itself fails after a preserved-segment compaction. Here, the rewind succeeds and every later send fails.

Possible fixes

  • Before rollback, check whether a compact_boundary exists after the target message. If one does, fork or truncate the transcript at the target instead of only pinning resumeSessionAt, or block the rollback with the existing "Start a new thread instead" message.
  • When the provider returns "No message found with message.uuid", let the user recover the thread (for example, drop the pinned resume point or fork from durable history), so that the thread does not stay broken.

Impact

Blocks work completely

Version or commit

T3 Code Nightly 0.0.46-nightly.20261009.2861 (macOS)

Activity

  1. juliusmarminge commented on Oct 22, 2026

    @juliusmarminge
    Member

    Reproduced on current main b5a226e49c with the real web dev app on Linux and Claude Sonnet 5.5. Completed two turns, ran manual /compact (with preserved-message metadata), completed another turn, then used Edit from here on the second prompt and Revert and keep changes. The rewind succeeded; three subsequent sends each failed with No message found with message.uuid for the retained first assistant message. The transcript still contains that message before the compaction boundary. Runtime transcript.

  2. acouhier commented on Oct 30, 2026

    @acouhier

    Still happens on T3 Code v0.1.5 (desktop app, macOS arm64, Claude Opus 5.5).

    • Manual /compact during a run (trigger: "manual"), then a revert to the end of an earlier run.
    • Every send then failed within about 2 s with No message found with message.uuid of: <X>.
    • Truncating the transcript right after <X> fixed the thread, as described in the issue.
    Details
    • query.open options on the failing sends: resume: <session>, resumeSessionAt: <X>
    • The result was error_during_execution, num_turns: 0
    • The compact_boundary comes after <X> in the transcript and belongs to a rolled-back run
    • On v0.1.5, resolveClaudeRollbackResumeSessionAt still returns the turn cursor without checking for a later boundary

    Reported via T3 Code triage by Claude Code (Claude Opus 5.5).

  3. madebyjulz commented on Nov 3, 2026

    @madebyjulz

    Still happens on T3 Code 0.1.7-nightly.20261103.4119 (desktop app, local server, macOS arm64, Claude Opus 5.5, Claude Code CLI 2.1.317).

    Sequence:

    1. Turns 1–4 completed normally. The last assistant message of turn 4 is <X>.
    2. Turn 5: a normal prompt. Turn 6: manual /compact, which wrote a compact_boundary (parentUuid: null, logicalParentUuid set).
    3. Reverted to the end of turn 4. Runs 5 and 6 became rolled_back, and the provider-thread.rollback effect succeeded.
    4. Every send after that (/compact, then a normal prompt) failed in about 1.5 s with Provider error: No message found with message.uuid of: <X> (error_during_execution, providerTurnId: null).

    In the session transcript, <X> is at line 490, and the compact_boundary from the rolled-back run is at line 548. resolveClaudeRollbackResumeSessionAt returns the turn 4 cursor as nativeConversationHeadRef, but the transcript is left as it is. So the CLI loads only the chain after the boundary and can't find <X>.

    The workaround from the issue still works: back up the transcript and truncate it right after <X>.

    Comment prepared by Claude Opus 5.5 (Claude Code) via T3 Code triage.

  4. TonybynMp4 commented on Nov 9, 2026

    @TonybynMp4
    Contributor

    Still happens on T3 Code 0.1.8-nightly.20261109.4399 (desktop, Linux, Claude Code CLI 2.1.319, Opus 5.5). With two Claude instances, the broken pin can stay hidden for hours and then show up after a context handoff, which makes it look like a handoff bug.

    Setup: two claudeAgent instances with different homes, "Perso" (homePath: ~/.claude-p) and "Pro" (default ~/.claude). One thread switches between them with context handoffs.

    Sequence, from the projection and the Pro transcript:

    1. On Pro, runs 46 to 48 complete. The last assistant message of run 48 is <X>.
    2. Run 51 on Pro is a manual /compact, which writes a compact_boundary to the Pro transcript.
    3. I revert to the end of run 48, so runs 49 to 52 become rolled_back. The Pro provider thread gets nativeConversationHeadRef: <X> (weak).
    4. I switch to Perso. A delta_since_target_last_seen handoff runs and seven turns complete normally. Pro's provider thread stays idle, with its head still pinned to <X>.
    5. Four hours later I switch back to Pro. The orchestrator reuses Pro's existing root provider thread, and the send fails in about 2 s with No message found with message.uuid of: <X>. The UI shows it right under the "Context handoff" divider. Every later send to Pro fails the same way.

    <X> is still in the Pro transcript, before the compact_boundary from the rolled-back run 51, which is the cause this issue describes. The handoff only reveals it.

    Recovery without editing the transcript: switch the thread to another Claude instance or another provider and send again. The thread continues there through a handoff. Pro's provider thread is still pinned to <X>, so switching back to Pro fails again until the transcript is truncated as described above.

    Revert can't get the user out of this either. Runs after a handoff have no provider turn on the active provider thread, so "Edit from here" and revert are hidden on those messages (deriveAvailableRevertTurnCounts). The only way out from the UI is changing provider, which most people won't think of. Clearing or repairing the pin when resume fails with this error, as the issue suggests, would cover this case too.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions