deepset-ai/haystack · error · ValueError

A `ChatMessage` must contain at least one `TextContent`, `To

Error message

A `ChatMessage` must contain at least one `TextContent`, `ToolCall`, `ToolCallResult`, or `ImageContent`.

What it means

ValueError raised in `convert_message_to_hf_format` when a ChatMessage's content list contains none of the content types the Hugging Face API can represent: TextContent, ToolCall, ToolCallResult, or ImageContent. ReasoningContent is deliberately excluded from this validation because it is for human transparency only and is never sent to the API, so a message containing only ReasoningContent is treated as empty.

Source

Thrown at haystack/utils/hf.py:73

    """
    Convert a message to the format expected by Hugging Face.

    Note: ReasoningContent is skipped during conversion because the HuggingFace Inference API
    (which follows the OpenAI-compatible chat completion format) does not support reasoning
    in input messages. Reasoning is captured from model outputs for transparency but is not
    sent back to the API in multi-turn conversations.
    """
    text_contents = message.texts
    tool_calls = message.tool_calls
    tool_call_results = message.tool_call_results
    images = message.images

    # Filter out ReasoningContent from the content list for validation
    # ReasoningContent is for human transparency only, not sent to the API
    non_reasoning_content = [c for c in message._content if not isinstance(c, ReasoningContent)]

    if not text_contents and not tool_calls and not tool_call_results and not images:
        raise ValueError(
            "A `ChatMessage` must contain at least one `TextContent`, `ToolCall`, `ToolCallResult`, or `ImageContent`."
        )
    if len(tool_call_results) > 0 and len(non_reasoning_content) > 1:
        raise ValueError(
            "For compatibility with the Hugging Face API, a `ChatMessage` with a `ToolCallResult` "
            "cannot contain any other content."
        )

    # HF always expects a content field, even if it is empty
    hf_msg: dict[str, Any] = {"role": message._role.value, "content": ""}

    if tool_call_results:
        result = tool_call_results[0]
        hf_msg["content"] = result.result
        if tc_id := result.origin.id:
            hf_msg["tool_call_id"] = tc_id
        # HF does not provide a way to communicate errors in tool invocations, so we ignore the error field
        return hf_msg

View on GitHub (pinned to e318778c9b)

Solutions

  1. Ensure the ChatMessage contains at least one TextContent, ToolCall, ToolCallResult, or ImageContent before conversion
  2. If the message only holds ReasoningContent, skip sending it to the generator or append a fallback TextContent
  3. Use ChatMessage.from_assistant/from_user with non-empty content

Example fix

// before
msg = ChatMessage.from_assistant("")  # or only ReasoningContent
hf = convert_message_to_hf_format(msg)
// after
msg = ChatMessage.from_assistant("Here is the answer.")
hf = convert_message_to_hf_format(msg)
Defensive patterns

Strategy: validation

Validate before calling

from haystack.dataclasses import TextContent, ToolCall, ToolCallResult, ImageContent
from haystack.utils import ReasoningContent
def is_hf_convertible(msg) -> bool:
    return any(not isinstance(c, ReasoningContent) for c in msg._content)

Type guard

def has_sendable_content(msg) -> bool:
    from haystack.dataclasses import TextContent, ToolCall, ToolCallResult, ImageContent
    return any(isinstance(c, (TextContent, ToolCall, ToolCallResult, ImageContent)) for c in msg._content)

Try / catch

try:
    hf_msg = convert_message_to_hf_format(msg)
except ValueError:
    hf_msg = None  # skip message or substitute a placeholder TextContent

Prevention

When it happens

Trigger: Calling convert_message_to_hf_format (or HuggingFaceAPIChatGenerator, which uses it) with a ChatMessage built solely from ReasoningContent, or from an empty content list, e.g. ChatMessage.from_assistant('') with no tool calls or images.

Common situations: Constructing assistant messages from LLM responses that contained only reasoning/thinking content; stripping content from a message during preprocessing; serializing placeholder messages.

Related errors


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