{"record":{"id":"1c512088c90777d5","repo":"deepset-ai/haystack","slug":"unsupported-tool-result-result-result","errorCode":null,"errorMessage":"Unsupported tool result: {result.result}","messagePattern":"Unsupported tool result: (.+?)","errorType":"exception","errorClass":"ValueError","httpStatus":null,"severity":"error","filePath":"haystack/components/generators/chat/openai_responses.py","lineNumber":1027,"sourceCode":"\n    # user message\n    if message._role.value == \"user\":\n        content = [convert_part(part) for part in message._content]\n        openai_msg[\"content\"] = content\n        return [openai_msg]\n\n    # tool message\n    if tool_call_results:\n        formatted_tool_results = []\n        for result in tool_call_results:\n            if result.origin.id is not None:\n                # Handle multimodal tool results (list of TextContent/ImageContent/FileContent)\n                if isinstance(result.result, list):\n                    output_content = [convert_part(part) for part in result.result]\n                elif isinstance(result.result, str):\n                    output_content = [{\"type\": \"input_text\", \"text\": result.result}]\n                else:\n                    raise ValueError(f\"Unsupported tool result: {result.result}\")\n                tool_result = {\n                    \"type\": \"function_call_output\",\n                    \"call_id\": result.origin.extra.get(\"call_id\") if result.origin.extra else \"\",\n                    \"output\": output_content,\n                }\n                formatted_tool_results.append(tool_result)\n        formatted_messages.extend(formatted_tool_results)\n\n    # Note: the API expects a reasoning id even if there is no reasoning text\n    # function calls without reasoning ids are not supported by the API\n    if reasonings:\n        formatted_reasonings = []\n        for reasoning in reasonings:\n            # Streaming events (e.g. response.reasoning_summary_text.delta) store event-level\n            # fields like item_id, output_index, summary_index, event_id, sequence_number into\n            # reasoning.extra. Those are not valid reasoning input item fields and the API\n            # rejects them with \"Unknown parameter\" when sent back in subsequent turns.\n            # Valid fields per ResponseReasoningItem schema: id, type, summary (handled separately),","sourceCodeStart":1009,"sourceCodeEnd":1045,"githubUrl":"https://github.com/deepset-ai/haystack/blob/e318778c9bf60a1963e3b5f451359655dd696c30/haystack/components/generators/chat/openai_responses.py#L1009-L1045","documentation":"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.","triggerScenarios":"Constructing a ToolCallResult whose `result` field is a dict/None/custom object, then passing the message through _convert_chat_message_to_responses_format.","commonSituations":"Returning parsed JSON objects or dicts from tools and stuffing them directly into ToolCallResult instead of serializing to a string.","solutions":["Serialize the tool result before creating the ToolCallResult: json.dumps(result) or str(result)","Convert structured results into a list of TextContent parts","Check ToolCallResult.result type before sending the message"],"exampleFix":"// before\nToolCallResult(result={\"answer\": 42})\n// after\nimport json\nToolCallResult(result=json.dumps({\"answer\": 42}))","handlingStrategy":"validation","validationCode":"from haystack.dataclasses import TextContent, ImageContent, FileContent\nfor m in messages:\n    for r in m.tool_call_results:\n        ok = isinstance(r.result, str) or (isinstance(r.result, list) and all(isinstance(p, (TextContent, ImageContent, FileContent)) for p in r.result))\n        assert ok, type(r.result)","typeGuard":"def is_supported_tool_result(r) -> bool:\n    from haystack.dataclasses import TextContent, ImageContent, FileContent\n    return isinstance(r.result, str) or (isinstance(r.result, list) and all(isinstance(p, (TextContent, ImageContent, FileContent)) for p in r.result))","tryCatchPattern":"try:\n    gen.run(messages=messages)\nexcept ValueError as e:\n    if \"Unsupported tool result\" in str(e):\n        messages = [stringify_tool_results(m) for m in messages]","preventionTips":["Serialize tool outputs to str (json.dumps) before wrapping","Only use str or TextContent/ImageContent/FileContent lists","Avoid dicts/None in ToolCallResult.result"],"tags":["python","haystack","openai","tool-result","type-error"],"backgroundTag":"unsupported-tool-result-type","analyzedSha":"e318778c9bf60a1963e3b5f451359655dd696c30","analyzedAt":"2026-08-30T11:45:20.711Z","schemaVersion":2},"datasetVersion":"2026-08-30T13:17:10.514Z"}