deepset-ai/haystack · error · ValueError
For OpenAI compatibility, a `ChatMessage` with a `ToolCallRe
Error message
For OpenAI compatibility, a `ChatMessage` with a `ToolCallResult` cannot contain any other content.
What it means
The OpenAI Responses API models tool results as standalone function_call_output items with no mixed content. haystack therefore rejects ChatMessages that contain a ToolCallResult together with any other content part (except a single one).
Source
Thrown at haystack/components/generators/chat/openai_responses.py:1001
"filename": part.filename or "filename",
"file_data": f"data:{part.mime_type or 'application/pdf'};base64,{part.base64_data}",
}
raise ValueError(f"Unsupported content type: {type(part)}")
text_contents = message.texts
tool_calls = message.tool_calls
tool_call_results = message.tool_call_results
images = message.images
reasonings = message.reasonings
files = message.files
if not any([text_contents, tool_calls, tool_call_results, images, reasonings, files]):
raise ValueError(
"""A `ChatMessage` must contain at least one `TextContent`, `ToolCall`, `ToolCallResult`,
`ImageContent`, `FileContent`, or `ReasoningContent`."""
)
if len(tool_call_results) > 0 and len(message._content) > 1:
raise ValueError(
"For OpenAI compatibility, a `ChatMessage` with a `ToolCallResult` cannot contain any other content."
)
formatted_messages: list[dict[str, Any]] = []
openai_msg: dict[str, Any] = {"role": message._role.value}
if message._name is not None:
openai_msg["name"] = message._name
# 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:View on GitHub (pinned to e318778c9b)
Solutions
- Put the ToolCallResult in its own ChatMessage with no other content
- Move accompanying text into a separate assistant/user message
- Rebuild the message: ChatMessage from only the ToolCallResult content
Example fix
// before
msg = ChatMessage(_role=role, _content=[tool_result, TextContent(text="done")])
// after
msg_tool = ChatMessage(_role=role, _content=[tool_result])
msg_text = ChatMessage.from_user("done") Defensive patterns
Strategy: validation
Validate before calling
from haystack.dataclasses import ToolCallResult
for m in messages:
if any(isinstance(p, ToolCallResult) for p in m._content) and len(m._content) > 1:
raise ValueError("ToolCallResult must be alone in its message") Type guard
def is_tool_result_only(m) -> bool:
from haystack.dataclasses import ToolCallResult
return len(m._content) == 1 and isinstance(m._content[0], ToolCallResult) Try / catch
try:
gen.run(messages=messages)
except ValueError as e:
if "ToolCallResult" in str(e):
messages = split_tool_results_into_own_messages(messages) Prevention
- One ToolCallResult per message
- Put commentary text in a separate message
- Follow OpenAI Responses API tool-call semantics
When it happens
Trigger: Appending a ToolCallResult to a message that also has TextContent/ImageContent/etc., then passing it to OpenAIResponsesChatGenerator.
Common situations: Merging tool output and commentary in one message (a habit from other APIs like Anthropic or openai chat completions where tool role messages can mix).
Related errors
- Unsupported content type: {type(part)}
- Unsupported tool result: {result.result}
- Cannot stream multiple responses, please set n=1.
- A `ChatMessage` must contain at least one `TextContent`, `To
- Document with ID '{doc.id}' comes from the PDF file '{resolv
AI-assisted analysis of deepset-ai/haystack@e318778c9b (2026-08-30).
Data as JSON: /api/errors/b7e0459299b7e2fd.
Report an issue: GitHub.