wavetermdev/waveterm · error
tool result missing ToolUseID
Error message
tool result missing ToolUseID
What it means
Each tool result must reference the tool_use block it responds to via ToolUseID. The Anthropic API requires tool_result blocks to carry a tool_use_id; a result with an empty ToolUseID cannot be mapped and conversion aborts before any API call.
Source
Thrown at pkg/aiusechat/anthropic/anthropic-convertmessage.go:757
// Copy each content block and clean it (strips internal fields)
for i, block := range msg.Content {
converted.Content[i] = *block.Clean()
}
return converted
}
// ConvertToolResultsToAnthropicChatMessage converts AIToolResult slice to anthropicChatMessage
func ConvertToolResultsToAnthropicChatMessage(toolResults []uctypes.AIToolResult) (*anthropicChatMessage, error) {
if len(toolResults) == 0 {
return nil, errors.New("toolResults cannot be empty")
}
var contentBlocks []anthropicMessageContentBlock
for _, result := range toolResults {
if result.ToolUseID == "" {
return nil, fmt.Errorf("tool result missing ToolUseID")
}
var content interface{}
var isError bool
if result.ErrorText != "" {
content = result.ErrorText
isError = true
} else {
// Check if text looks like an image data URL
if strings.HasPrefix(result.Text, "data:image/") {
// Parse the data URL to extract media type and base64 data
parts := strings.SplitN(result.Text, ",", 2)
if len(parts) == 2 {
// Extract media type from "data:image/png;base64"
mediaTypePart := strings.TrimPrefix(parts[0], "data:")
mediaType := strings.Split(mediaTypePart, ";")[0]
View on GitHub (pinned to a4447c1563)
Solutions
- Populate ToolUseID from the corresponding tool_use block id in the assistant message
- When streaming/iterating tool calls, capture each call's ID before executing the tool
- Add a pre-conversion check that every result has a non-empty ToolUseID
Example fix
// before
results := []uctypes.ToolResult{{Content: output}}
// after
results := []uctypes.ToolResult{{ToolUseID: assistantToolUseID, Content: output}} Defensive patterns
Strategy: validation
Validate before calling
for i, r := range toolResults {
if r.ToolUseID == "" { return fmt.Errorf("toolResults[%d] missing ToolUseID", i) }
} Try / catch
blocks, err := anthropic.ConvertToolResultsToAnthropicChatMessage(toolResults)
if err != nil && strings.Contains(err.Error(), "missing ToolUseID") {
return fmt.Errorf("internal: tool executor did not propagate tool_use id")
} Prevention
- Thread the tool_use id from the assistant message into every result at execution time
- Add a unit test asserting ToolUseID is set for each result
- Validate results at the tool-executor boundary, not just at conversion
When it happens
Trigger: Calling ConvertToolResultsToAnthropicChatMessage with a tool result entry where the ToolUseID field is the empty string.
Common situations: Constructing tool results manually and forgetting to copy the ID from the assistant's tool_use block; a previous pipeline step dropping the ID; deserialized results missing fields.
Understand the failure class
Background: "missing required argument" and "the following required arguments were not provided": what required-argument errors mean and how to fix them — this error's family across 20 libraries.
Related errors
- tool call with ID %s not found in chat %s
- invalid accumulated tool input JSON: %w
- tool input is not an object
- convertFileUIMessagePart expects 'file' type, got '%s'
- unsupported URL protocol in file part: %s
AI-assisted analysis of wavetermdev/waveterm@a4447c1563 (2026-09-01).
Data as JSON: /api/errors/fa7e640fbef1fbac.
Report an issue: GitHub.