-
-
Notifications
You must be signed in to change notification settings - Fork 40.1k
Closed
Labels
bugSomething isn't workingSomething isn't working
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().
Reactions are currently unavailable
Metadata
Metadata
Assignees
Labels
bugSomething isn't workingSomething isn't working