deepset-ai/haystack · error · ValueError

Unsupported tool result: {result.result}

Error message

Unsupported tool result: {result.result}

What it means

Tool call results in the Responses API conversion accept either a str or a list of TextContent/ImageContent/FileContent as their `result`. Any other payload type (dict, None, nested objects) raises ValueError since it cannot be mapped to `output` content.

Source

Thrown at haystack/components/generators/chat/openai_responses.py:1027

    # user message
    if message._role.value == "user":
        content = [convert_part(part) for part in message._content]
        openai_msg["content"] = content
        return [openai_msg]

    # tool message
    if tool_call_results:
        formatted_tool_results = []
        for result in tool_call_results:
            if result.origin.id is not None:
                # Handle multimodal tool results (list of TextContent/ImageContent/FileContent)
                if isinstance(result.result, list):
                    output_content = [convert_part(part) for part in result.result]
                elif isinstance(result.result, str):
                    output_content = [{"type": "input_text", "text": result.result}]
                else:
                    raise ValueError(f"Unsupported tool result: {result.result}")
                tool_result = {
                    "type": "function_call_output",
                    "call_id": result.origin.extra.get("call_id") if result.origin.extra else "",
                    "output": output_content,
                }
                formatted_tool_results.append(tool_result)
        formatted_messages.extend(formatted_tool_results)

    # Note: the API expects a reasoning id even if there is no reasoning text
    # function calls without reasoning ids are not supported by the API
    if reasonings:
        formatted_reasonings = []
        for reasoning in reasonings:
            # Streaming events (e.g. response.reasoning_summary_text.delta) store event-level
            # fields like item_id, output_index, summary_index, event_id, sequence_number into
            # reasoning.extra. Those are not valid reasoning input item fields and the API
            # rejects them with "Unknown parameter" when sent back in subsequent turns.
            # Valid fields per ResponseReasoningItem schema: id, type, summary (handled separately),

View on GitHub (pinned to e318778c9b)

Solutions

  1. Serialize the tool result before creating the ToolCallResult: json.dumps(result) or str(result)
  2. Convert structured results into a list of TextContent parts
  3. Check ToolCallResult.result type before sending the message

Example fix

// before
ToolCallResult(result={"answer": 42})
// after
import json
ToolCallResult(result=json.dumps({"answer": 42}))
Defensive patterns

Strategy: validation

Validate before calling

from haystack.dataclasses import TextContent, ImageContent, FileContent
for m in messages:
    for r in m.tool_call_results:
        ok = isinstance(r.result, str) or (isinstance(r.result, list) and all(isinstance(p, (TextContent, ImageContent, FileContent)) for p in r.result))
        assert ok, type(r.result)

Type guard

def is_supported_tool_result(r) -> bool:
    from haystack.dataclasses import TextContent, ImageContent, FileContent
    return isinstance(r.result, str) or (isinstance(r.result, list) and all(isinstance(p, (TextContent, ImageContent, FileContent)) for p in r.result))

Try / catch

try:
    gen.run(messages=messages)
except ValueError as e:
    if "Unsupported tool result" in str(e):
        messages = [stringify_tool_results(m) for m in messages]

Prevention

When it happens

Trigger: Constructing a ToolCallResult whose `result` field is a dict/None/custom object, then passing the message through _convert_chat_message_to_responses_format.

Common situations: Returning parsed JSON objects or dicts from tools and stuffing them directly into ToolCallResult instead of serializing to a string.

Related errors


AI-assisted analysis of deepset-ai/haystack@e318778c9b (2026-08-30). Data as JSON: /api/errors/1c512088c90777d5. Report an issue: GitHub.