Skip to content

[AI-Assisted] fix: skip tool_use blocks with stopReason error in transcript repair#3060

Closed
sid1943 wants to merge 1 commit intoopenclaw:mainfrom
sid1943:fix/skip-errored-tool-use-in-transcript-repair
Closed

[AI-Assisted] fix: skip tool_use blocks with stopReason error in transcript repair#3060
sid1943 wants to merge 1 commit intoopenclaw:mainfrom
sid1943:fix/skip-errored-tool-use-in-transcript-repair

Conversation

@sid1943
Copy link

@sid1943 sid1943 commented Jan 28, 2026

Summary

Fixes #1826

When an assistant message has stopReason: "error", the tool_use blocks within it are incomplete/terminated and were never actually executed. The transcript repair mechanism was incorrectly creating synthetic tool_results for these errored tool calls, causing all subsequent API requests to fail with:

invalid_request_error: messages.X.content.Y: unexpected tool_use_id found in tool_result blocks: toolu_XXX. 
Each tool_result block must have a corresponding tool_use block in the previous message.

This breaks the session permanently until the synthetic tool_result is manually removed from the JSONL file.

Changes

  • Check stopReason before extracting tool calls in repairToolUseResultPairing()
  • Skip tool call extraction when stopReason is "error"
  • Prevents synthetic tool_results for incomplete/terminated tool calls

Root Cause

The issue occurred in src/agents/session-transcript-repair.ts at line 119:

Before:

const assistant = msg as Extract<AgentMessage, { role: "assistant" }>;
const toolCalls = extractToolCallsFromAssistant(assistant);  // ❌ Extracts from errored messages too

After:

const assistant = msg as Extract<AgentMessage, { role: "assistant" }>;

// Skip tool call extraction if the assistant turn errored/terminated.
// When stopReason is "error", the tool_use blocks are incomplete and were never executed,
// so we should not create synthetic tool_results for them.
const stopReason = (assistant as { stopReason?: unknown }).stopReason;
if (stopReason === "error") {
  out.push(msg);
  continue;
}

const toolCalls = extractToolCallsFromAssistant(assistant);

Impact

Before this fix:

  • Tool execution error/interruption → session permanently broken
  • Requires manual JSONL editing to recover
  • Confusing error messages for users

After this fix:

  • Tool execution error/interruption → session remains usable
  • No manual intervention needed
  • Clean recovery from errors

Testing Status

⚠️ Lightly tested

  • ✅ TypeScript compiles without errors
  • ✅ Linter passes (oxlint)
  • ⚠️ No specific test for errored tool_use scenario (would need integration test with actual API error)
  • ⚠️ Needs real-world validation

Files Changed

  • src/agents/session-transcript-repair.ts - Added stopReason check (10 lines added)

AI-Assisted Development

🤖 This PR was created with assistance from Claude Sonnet 4.5

Checklist


Generated with Claude Code

Fixes openclaw#1826

When an assistant message has stopReason: error, the tool_use blocks
within it are incomplete/terminated and were never actually executed.
The transcript repair mechanism was incorrectly creating synthetic
tool_results for these errored tool calls, causing all subsequent
API requests to fail with:

  invalid_request_error: unexpected tool_use_id found in tool_result blocks

Changes:
- Check stopReason before extracting tool calls in repairToolUseResultPairing()
- Skip tool call extraction when stopReason is error
- Prevents synthetic tool_results for incomplete/terminated tool calls

This ensures sessions remain usable after tool execution errors or
interruptions, without requiring manual JSONL editing.

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
@sid1943
Copy link
Author

sid1943 commented Jan 28, 2026

Closing as duplicate. This issue is already being addressed by PRs #1859 and #3054 which were opened earlier.

The fix suggested in issue #1826 has already been implemented by other contributors.

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

Labels

agents Agent runtime and tooling

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Synthetic tool_result for terminated tool_use causes all subsequent requests to fail

1 participant