#9416: fix: drop errored/aborted assistant tool pairs in transcript repair
agents
stale
Cluster:
Error Handling in Agent Tools
## Problem
When an assistant message with tool calls errors or aborts during execution, the message is persisted with `stopReason: "error"` (or `"aborted"`) alongside its `toolResult` messages.
On subsequent turns, `repairToolUseResultPairing()` correctly pairs these tool results with the errored assistant. However, `pi-ai`'s `transformMessages()` then **strips the errored assistant** (it skips messages with `stopReason === "error" || "aborted"`) but **keeps the orphaned tool results**.
Those orphaned `tool_result` blocks get grouped with the preceding assistant's `tool_use` blocks in the API request, causing:
```
HTTP 400 invalid_request_error: unexpected tool_use_id found in tool_result blocks
```
This is a **session-killing error** — once triggered, every subsequent message fails with the same 400 until the errored messages are manually removed from the session file.
## Fix
When `repairToolUseResultPairing()` encounters an assistant message with `stopReason === "error" || "aborted"` that has tool calls, it now drops both the assistant message and its associated tool results. Non-tool messages in between (remainder) are preserved.
This runs before `transformMessages()`, so the orphaned blocks never reach the API.
## Test plan
- [x] 4 new test cases:
- drops errored assistant with tool calls and its tool results
- drops aborted assistant with tool calls and its tool results
- keeps errored assistant without tool calls (no change to existing behavior)
- preserves remainder messages when dropping errored assistant
- [x] All 10 existing + new tests pass
## Note
This is also a bug in `pi-ai`'s `transformMessages()` — when stripping errored/aborted assistant messages, it should also strip their associated tool results. This fix handles it at the openclaw layer as a defense-in-depth measure.
<!-- greptile_comment -->
<h2>Greptile Overview</h2>
<h3>Greptile Summary</h3>
This PR updates transcript repair (`repairToolUseResultPairing`) to detect assistant messages that stopped with `stopReason: "error" | "aborted"` *and* contain tool calls, and then drop that assistant turn along with its associated tool results. This prevents downstream message transformation (in `pi-ai`) from stripping the assistant while leaving orphaned tool results, which can cause Anthropic-compatible APIs to reject requests due to unexpected tool result IDs.
Tests were added to cover dropping errored/aborted tool-call assistants, preserving errored assistants without tool calls, and ensuring non-tool “remainder” messages are preserved when the errored span is removed.
<h3>Confidence Score: 4/5</h3>
- This PR is close to safe to merge, with one correctness concern around duplicate toolResult handling in the new drop branch.
- Core change is narrowly scoped and well-covered by new tests, but the new branch drops tool results without recording their IDs in the global duplicate tracker, which can let later duplicates through in transcripts that contain repeated tool result IDs.
- src/agents/session-transcript-repair.ts
<!-- greptile_other_comments_section -->
<sub>(3/5) Reply to the agent's comments like "Can you suggest a fix for this @greptileai?" or ask follow-up questions!</sub>
<!-- /greptile_comment -->
Most Similar PRs
#4844: fix(agents): skip error/aborted assistant messages in transcript re...
by lailoo · 2026-01-30
92.4%
#3880: fix: drop assistant messages with stopReason 'error' to avoid orpha...
by SalimBinYousuf1 · 2026-01-29
87.8%
#16966: fix: strip tool_use blocks from aborted/errored assistant messages
by StressTestor · 2026-02-15
87.5%
#12487: fix(agents): strip orphaned tool_result when tool_use is sanitized ...
by skylarkoo7 · 2026-02-09
87.4%
#7525: Agents: skip errored tool calls during pairing
by justinhuangcode · 2026-02-02
87.2%
#14328: fix: strip incomplete tool_use blocks from errored/aborted messages...
by Kropiunig · 2026-02-12
86.9%
#15050: fix: transcript corruption resilience — strip aborted tool_use bloc...
by yashchitneni · 2026-02-12
86.8%
#8345: fix: prevent synthetic error repair from creating tool_result for d...
by vishaltandale00 · 2026-02-03
85.6%
#13062: fix: remove orphaned tool_result blocks from user message content d...
by trevorgordon981 · 2026-02-10
85.4%
#3362: fix: auto-repair and retry on orphan tool_result errors
by samhotchkiss · 2026-01-28
85.2%