deepset-ai/haystack · error · ValueError
System message must contain only one text part.
Error message
System message must contain only one text part.
What it means
System messages built from a chat template may contain exactly one text part and nothing else. This error indicates the system message accumulated multiple text parts, which Haystack does not allow.
Source
Thrown at haystack/utils/jinja2_chat_extension.py:373
:raises ValueError: If content parts don't allow to build a valid ChatMessage object or the role is not
supported
"""
if role == "user":
valid_parts = [part for part in parts if isinstance(part, (TextContent, str, ImageContent, FileContent))]
if len(parts) != len(valid_parts):
raise ValueError(
"User message must contain only TextContent, string, ImageContent or FileContent parts."
)
return ChatMessage.from_user(meta=meta, name=name, content_parts=valid_parts)
if role == "system":
if not isinstance(parts[0], TextContent):
raise ValueError("System message must contain a text part.")
text = parts[0].text
if len(parts) > 1:
raise ValueError("System message must contain only one text part.")
return ChatMessage.from_system(meta=meta, name=name, text=text)
if role == "assistant":
texts = [part.text for part in parts if isinstance(part, TextContent)]
tool_calls = [part for part in parts if isinstance(part, ToolCall)]
reasoning = [part for part in parts if isinstance(part, ReasoningContent)]
if len(texts) > 1:
raise ValueError("Assistant message must contain one text part at most.")
if len(texts) == 0 and len(tool_calls) == 0:
raise ValueError("Assistant message must contain at least one text or tool call part.")
if len(parts) > len(texts) + len(tool_calls) + len(reasoning):
raise ValueError("Assistant message must contain only text, tool call or reasoning parts.")
return ChatMessage.from_assistant(
meta=meta,
name=name,
text=texts[0] if texts else None,
tool_calls=tool_calls or None,
reasoning=reasoning[0] if reasoning else None,View on GitHub (pinned to e318778c9b)
Solutions
- Combine the text into a single part, e.g. concatenate strings in Jinja2: {{ a }} {{ b }}.
- Insert only one ChatMessage into the system block, or merge messages before inserting.
- If multiple system messages are needed, send them as separate system ChatMessages rather than parts.
- Use message join logic outside the template to produce a single text string.
Example fix
// before
{% insert %}{{ msg_a }}{% endinsert %}{% insert %}{{ msg_b }}{% endinsert %}
// after
{{ msg_a.text }}\n{{ msg_b.text }} // single text part Defensive patterns
Strategy: validation
Validate before calling
from haystack.dataclasses import ChatMessage, TextContent
def validate_single_text_system(msg: ChatMessage):
texts = [p for p in msg.content_parts if isinstance(p, TextContent)]
if len(msg.content_parts) != 1 or len(texts) != 1:
raise TypeError("System message must be exactly one TextContent part") Type guard
def is_single_text(msg: ChatMessage) -> bool:
parts = msg.content_parts
return len(parts) == 1 and isinstance(parts[0], TextContent) Try / catch
try:
messages = renderer.run(template=tpl, variables=vars)["messages"]
except ValueError as e:
if "only one text part" in str(e):
log.error("Multiple text parts in system message; merge texts before rendering")
raise Prevention
- Concatenate text in Jinja2 ({{ a }} {{ b }}) instead of multiple inserts.
- Merge multiple system prompts into one string before rendering.
- Limit system blocks to a single text variable or single inserted message.
- Avoid loops inside system message blocks.
When it happens
Trigger: Multiple {% insert %} expressions or several text segments inside a system message block, each producing its own TextContent part; inserting a list of multiple messages into a system block.
Common situations: Concatenating multiple instruction messages into one system prompt via insert; a loop inside the system block emitting several text parts; merging system prompts from multiple components.
Related errors
- System message must contain a text part.
- User message must contain only TextContent, string, ImageCon
- Assistant message must contain one text part at most.
- Assistant message must contain at least one text or tool cal
- Assistant message must contain only text, tool call or reaso
AI-assisted analysis of deepset-ai/haystack@e318778c9b (2026-08-30).
Data as JSON: /api/errors/7a95909c85d8728a.
Report an issue: GitHub.