wavetermdev/waveterm · error
tool result missing ToolUseID
Error message
tool result missing ToolUseID
What it means
ConvertToolResultsToOpenAIChatMessage requires every tool result to carry the ToolUseID that links it back to the assistant's tool call; if result.ToolUseID is empty it cannot emit the function_call_output, so it fails fast with this error.
Source
Thrown at pkg/aiusechat/openai/openai-convertmessage.go:467
MessageId: aiMsg.MessageId,
Message: &OpenAIMessage{
Role: "user",
Content: contentBlocks,
},
}, nil
}
// ConvertToolResultsToOpenAIChatMessage converts AIToolResult slice to OpenAIChatMessage slice
func ConvertToolResultsToOpenAIChatMessage(toolResults []uctypes.AIToolResult) ([]*OpenAIChatMessage, error) {
if len(toolResults) == 0 {
return nil, errors.New("toolResults cannot be empty")
}
var messages []*OpenAIChatMessage
for _, result := range toolResults {
if result.ToolUseID == "" {
return nil, fmt.Errorf("tool result missing ToolUseID")
}
// Create the function call output with result data
var outputData any
if result.ErrorText != "" {
// Marshal error output to string
errorOutput := OpenAIFunctionCallErrorOutput{
Ok: "false",
Error: result.ErrorText,
}
errorBytes, err := json.Marshal(errorOutput)
if err != nil {
return nil, fmt.Errorf("failed to marshal error output: %w", err)
}
outputData = string(errorBytes)
} else {
// Check if text looks like an image data URL
if strings.HasPrefix(result.Text, "data:image/") {View on GitHub (pinned to a4447c1563)
Solutions
- Set ToolUseID from the corresponding assistant tool-call ID when building each result
- Filter out results with empty ToolUseID before conversion if they are genuinely orphaned
- Check the persistence layer isn't dropping the ToolUseID field on round-trip
Example fix
// before
results := []ToolResult{{Text: "42"}}
// after
results := []ToolResult{{ToolUseID: toolCall.ID, Text: "42"}} Defensive patterns
Strategy: validation
Validate before calling
for i, r := range toolResults {
if r.ToolUseID == "" { return fmt.Errorf("tool result %d missing ToolUseID", i) }
} Prevention
- Always copy the assistant tool-call ID into the result's ToolUseID
- Validate results before persistence and again before conversion
- Don't drop fields when serializing tool results
When it happens
Trigger: Passing a []ToolResult to ConvertToolResultsToNativeChatMessage / ConvertToolResultsToOpenAIChatMessage where at least one entry has ToolUseID == "" — e.g. results created without recording the originating call's ID.
Common situations: Hand-building tool results in tests; dropping the ID when persisting/reloading tool results from a store; constructing results from a tool executor that isn't given the call ID.
Related errors
- chatOpts.ClientId is required
- function call with callId %s not found in chat %s
- convertFileAIMessagePart expects 'file' type, got '%s'
- file part missing mimetype
- invalid AIMessage: %w
AI-assisted analysis of wavetermdev/waveterm@a4447c1563 (2026-09-01).
Data as JSON: /api/errors/87484e107351c769.
Report an issue: GitHub.