deepset-ai/haystack · error · ValueError
Message content in template is empty or contains only whites
Error message
Message content in template is empty or contains only whitespace characters. Content: {content!r} What it means
During template rendering, a message block produced content that is empty or whitespace-only after parsing the sentinel-tagged content parts. Haystack rejects this because a ChatMessage cannot be built from empty content.
Source
Thrown at haystack/utils/jinja2_chat_extension.py:301
@staticmethod
def _parse_content_parts(content: str, start_tag: str, end_tag: str) -> list[ChatMessageContentT]:
"""
Parse a string into a sequence of ChatMessageContentT objects.
This method handles:
- Plain text content, converted to TextContent objects
- Structured content parts wrapped in sentinel tags, converted to ChatMessageContentT objects
:param content: Input string containing mixed text and content parts
:param start_tag: The opening sentinel tag (including the nonce)
:param end_tag: The closing sentinel tag (including the nonce)
:return: A list of ChatMessageContentT objects
:raises ValueError: If the content is empty or contains only whitespace characters or if a
`<haystack_content_part>` tag is found without a matching closing tag.
"""
if not content.strip():
raise ValueError(
f"Message content in template is empty or contains only whitespace characters. "
f"Content: {_redact_nonce(content, start_tag, end_tag)!r}"
)
parts: list[ChatMessageContentT] = []
cursor = 0
total_length = len(content)
while cursor < total_length:
tag_start = content.find(start_tag, cursor)
if tag_start == -1:
# No more tags, add remaining text if any
remaining_text = content[cursor:].strip()
if remaining_text:
parts.append(TextContent(text=remaining_text))
break
View on GitHub (pinned to e318778c9b)
Solutions
- Ensure the expression inside the message block always yields non-empty text, e.g. {{ var or "default" }}.
- Guard with Jinja2 conditionals: {% if var %}...{% endif %} around the message content.
- Check the pipeline variables passed to the template renderer for empty/None values.
- Verify the variable names in the template match the provided variables dict exactly.
Example fix
// before
"""User message: {{ query }}""" # query is empty
// after
"""User message: {{ query or "(no query provided)" }}""" Defensive patterns
Strategy: validation
Validate before calling
def validate_template_vars(vars: dict):
for k, v in vars.items():
if v is None or (isinstance(v, str) and not v.strip()):
raise ValueError(f"Template variable '{k}' is empty or whitespace-only") Type guard
def has_content(v) -> bool:
return v is not None and (not isinstance(v, str) or bool(v.strip())) Try / catch
try:
messages = renderer.run(template=tpl, variables=vars)["messages"]
except ValueError as e:
if "empty or contains only whitespace" in str(e):
raise ValueError(f"Template produced empty message; check variables: {list(vars)}") from e
raise Prevention
- Use Jinja2 defaults: {{ var or "fallback" }} or {% if var %} guards.
- Validate all template variables for emptiness before rendering.
- Avoid filters that can produce empty strings (e.g. truncate(0)).
- Double-check variable name spelling against the variables dict.
When it happens
Trigger: A Jinja2 expression inside a message block evaluates to an empty string, None, or only whitespace (e.g. {{ optional_var }} where the variable is empty), and the message carries no content parts.
Common situations: Optional context variables that end up empty; a filter that strips content (e.g. truncate to 0); loops that produce nothing; templates where a variable name is misspelled and renders as empty.
Related errors
- The '{% insert %}' expression must evaluate to a ChatMessage
- Found unclosed <haystack_content_part> tag at position {tag_
- A `ChatMessage` must contain at least one `TextContent`, `To
- Invalid template for condition: {condition_value}
- Invalid template for output: {output!r} (type: {type(output)
AI-assisted analysis of deepset-ai/haystack@e318778c9b (2026-08-30).
Data as JSON: /api/errors/5e333e2904c2736d.
Report an issue: GitHub.