deepset-ai/haystack · error · ValueError

{prompt_label} must render to exactly one {expected_role.val

Error message

{prompt_label} must render to exactly one {expected_role.value} message. Got {len(prompt_messages)} messages.

What it means

Raised by _render_prompt_messages when the ChatPromptBuilder renders the prompt into zero or multiple messages instead of exactly one of the expected role. The Agent requires a single rendered message per prompt at execution setup time.

Source

Thrown at haystack/components/agents/utils.py:297


def _render_prompt_messages(
    *, prompt_builder: ChatPromptBuilder, expected_role: ChatRole, prompt_label: str, kwargs: dict[str, Any]
) -> list[ChatMessage]:
    """
    Render one Agent prompt and validate the rendered message.

    :param prompt_builder: Builder configured with the prompt template.
    :param expected_role: Role the rendered message must have.
    :param prompt_label: Prompt name used in error messages.
    :param kwargs: Runtime values available to the prompt template.
    :returns: A single rendered prompt message.
    :raises ValueError: If the prompt renders to zero, multiple, or wrong-role messages.
    """
    prompt_kwargs = {var: kwargs[var] for var in prompt_builder.variables if var in kwargs}
    prompt_messages = prompt_builder.run(**prompt_kwargs)["prompt"]
    if len(prompt_messages) != 1:
        raise ValueError(
            f"{prompt_label} must render to exactly one {expected_role.value} message. "
            f"Got {len(prompt_messages)} messages."
        )
    if not prompt_messages[0].is_from(expected_role):
        raise ValueError(
            f"{prompt_label} must render to a {expected_role.value} message. "
            f"Got a message with role {prompt_messages[0].role}."
        )
    return prompt_messages

View on GitHub (pinned to e318778c9b)

Solutions

  1. Ensure the prompt template renders exactly one message block for all valid variable values.
  2. Inspect the template variables being passed in kwargs and simplify any that expand into several messages.
  3. Pre-render the prompt with the same variables using ChatPromptBuilder to verify output count before running the Agent.

Example fix

// before (template loops produce many messages)
prompt = "{% for q in queries %}{% message role='user' %}{{ q }}{% endmessage %}{% endfor %}"
// after
prompt = "{% message role='user' %}{{ queries|join('; ') }}{% endmessage %}"
Defensive patterns

Strategy: validation

Validate before calling

from haystack.components.builders import ChatPromptBuilder
pb = ChatPromptBuilder(variables=list(vars_), template=[template_message])
out = pb.run(**kwargs)["prompt"]
assert len(out) == 1, f"prompt renders {len(out)} messages"

Try / catch

try:
    agent.run(query=q, **extra)
except ValueError as e:
    if "must render to exactly one" in str(e):
        logging.error("Prompt rendering issue: %s", e)
    raise

Prevention

When it happens

Trigger: Passing template variables (via run kwargs) that cause the prompt template to emit multiple message blocks, or a prompt whose Jinja template conditionally yields nothing/multiple messages.

Common situations: Template variables expanding into multiple messages; a custom prompt string with loops over messages; kwargs that change the rendered structure at runtime rather than init time.

Related errors


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