-
Notifications
You must be signed in to change notification settings - Fork 15.7k
Description
Bug Description
LLM API requests are rejected with the error:
messages.136.content.1: unexpected tool_use_id found in tool_result blocks: toolu_01Q1BaXmp2s7A2Xqu18Zd9mR. Each tool_result block must have a corresponding tool_use block in the previous message.
Root Cause
In dist/agents/pi-embedded-runner/run/attempt.js, the message processing pipeline has a synchronization bug:
- Line 431-439:
sanitizeSessionHistory()callsrepairToolUseResultPairing()to fix tool_use/tool_result pairings - Line 447:
limitHistoryTurns()runs AFTER the repair, truncating conversation history - The truncation can cut between an assistant message (with
tool_use) and itstool_result, creating orphanedtool_resultblocks that reference non-existenttool_use_ids - The Anthropic API rejects the malformed transcript
Code Location
File: dist/agents/pi-embedded-runner/run/attempt.js (lines 431-451)
const prior = await sanitizeSessionHistory({...}); // Repairs pairings
const validatedGemini = transcriptPolicy.validateGeminiTurns
? validateGeminiTurns(prior)
: prior;
const validated = transcriptPolicy.validateAnthropicTurns
? validateAnthropicTurns(validatedGemini)
: validatedGemini;
const limited = limitHistoryTurns(validated, ...); // BUG: Truncates AFTER repair!File: dist/agents/pi-embedded-runner/history.js (lines 10-24)
The limitHistoryTurns() function counts user turns backwards and slices at a user message boundary, which can split assistant+tool_result pairs.
Proposed Fix
Call sanitizeToolUseResultPairing() after limitHistoryTurns() to repair any pairings broken by truncation:
import { sanitizeToolUseResultPairing } from "../../session-transcript-repair.js";
// ... existing code ...
const limited = limitHistoryTurns(validated, getDmHistoryLimitFromSessionKey(...));
// Fix: Repair tool_use/tool_result pairings AFTER truncation
const repaired = sanitizeToolUseResultPairing(limited);
cacheTrace?.recordStage("session:limited", { messages: repaired });
if (repaired.length > 0) {
activeSession.agent.replaceMessages(repaired);
}Reproduction
- Have a long DM conversation with many tool calls
- Configure
dmHistoryLimitto a value that truncates history - The truncation cuts between an assistant tool_use and its tool_result
- Next LLM request fails with "unexpected tool_use_id" error
Environment
- clawdbot version: 2026.1.24-3
- Node.js version: 22.x
- Platform: Linux
Additional Context
The transcript-sanitize.js extension also calls repairToolUseResultPairing() on the context event, but this runs before the truncation in attempt.js, so it doesn't catch pairings broken by limitHistoryTurns().
Metadata
Metadata
Assignees
Labels
No labels