deepset-ai/haystack · error · ValueError

The {self.__class__.__name__} expects a list containing only

Error message

The {self.__class__.__name__} expects a list containing only ChatMessage instances. The provided list contains other types. Please ensure that all elements in the list are ChatMessage instances.

What it means

ChatPromptBuilder.run raises when a list template is supplied but one or more elements are not ChatMessage instances. The builder can only render ChatMessage templates, so mixed or wrong-typed lists are rejected.

Source

Thrown at haystack/components/builders/chat_prompt_builder.py:253

            - `prompt`: The updated list of `ChatMessage` objects after rendering the templates.
        :raises ValueError:
            If `chat_messages` is empty or contains elements that are not instances of `ChatMessage`.
        """
        kwargs = kwargs or {}
        template_variables = template_variables or {}
        template_variables_combined = {**kwargs, **template_variables}

        if template is None:
            template = self.template

        if not template:
            raise ValueError(
                f"The {self.__class__.__name__} requires a non-empty list of ChatMessage instances. "
                f"Please provide a valid list of ChatMessage instances to render the prompt."
            )

        if isinstance(template, list) and not all(isinstance(message, ChatMessage) for message in template):
            raise ValueError(
                f"The {self.__class__.__name__} expects a list containing only ChatMessage instances. "
                f"The provided list contains other types. Please ensure that all elements in the list "
                f"are ChatMessage instances."
            )

        processed_messages = []
        if isinstance(template, list):
            for message in template:
                if message.is_from(ChatRole.USER) or message.is_from(ChatRole.SYSTEM):
                    self._validate_variables(set(template_variables_combined.keys()))
                    if message.text is None:
                        raise ValueError(NO_TEXT_ERROR_MESSAGE.format(role=message.role.value, message=message))
                    if message.text and "templatize_part" in message.text:
                        raise ValueError(FILTER_NOT_ALLOWED_ERROR_MESSAGE)
                    compiled_template = self._env.from_string(message.text)
                    rendered_text = compiled_template.render(template_variables_combined)
                    # use dataclasses.replace to avoid in-place mutation of the original message
                    rendered_message: ChatMessage = replace(message, _content=[TextContent(text=rendered_text)])

View on GitHub (pinned to e318778c9b)

Solutions

  1. Wrap plain strings in ChatMessage objects, e.g. ChatMessage.from_user(text).
  2. Validate all elements with isinstance(m, ChatMessage) before calling run.
  3. If you have string templates, use PromptBuilder or convert them to ChatMessage lists first.

Example fix

// before
builder.run(template=['Hello {{ name }}'])
// after
builder.run(template=[ChatMessage.from_user('Hello {{ name }}')])
Defensive patterns

Strategy: type-guard

Validate before calling

from haystack.dataclasses import ChatMessage
assert all(isinstance(m, ChatMessage) for m in template), 'all elements must be ChatMessage'

Type guard

def all_chat_messages(t: list) -> bool:
    return isinstance(t, list) and all(isinstance(m, ChatMessage) for m in t)

Try / catch

try:
    res = builder.run(template=template, **kwargs)
except ValueError as e:
    if 'only ChatMessage instances' in str(e):
        template = [ChatMessage.from_user(m) if isinstance(m, str) else m for m in template]
        res = builder.run(template=template, **kwargs)
    else:
        raise

Prevention

When it happens

Trigger: Calling run(template=[...]) where the list contains plain strings, dicts, or a mix of str and ChatMessage.

Common situations: Reusing a PromptBuilder-style string list; constructing messages by hand and accidentally appending raw strings; deserialization returning dicts instead of ChatMessage objects.

Understand the failure class

Background: Invalid argument type errors: "must be of type string", "expected X, got Y", and ERR_INVALID_ARG_TYPE explained — this error's family across 15 libraries.

Related errors


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