deepset-ai/haystack · error · ValueError
Invalid template for output: {output!r} (type: {type(output)
Error message
Invalid template for output: {output!r} (type: {type(output).__name__}). Output must be a string representing a valid Jinja2 template. For example, use {str(output)!r} instead of {output!r}. What it means
ConditionalRouter validates each route's 'output' as a Jinja2 template string in _validate_routes (called from __init__) unless output_passthrough is set. A non-string output (or an invalid template string) raises this ValueError with the value and its type.
Source
Thrown at haystack/components/routers/conditional_router.py:527
# Condition is always a Jinja2 template — validate it
if not self._validate_template(self._env, route["condition"]):
condition_value = route["condition"]
if not isinstance(condition_value, str):
raise ValueError(
f"Invalid template for condition: {condition_value!r} (type: {type(condition_value).__name__})."
f"Condition must be a string representing a valid Jinja2 template. "
f"For example, use {str(condition_value)!r} instead of {condition_value!r}."
)
raise ValueError(f"Invalid template for condition: {condition_value}")
# Only validate output as Jinja2 template when output_passthrough is False (default)
output_passthrough = route.get("output_passthrough", False)
if not output_passthrough:
for output in outputs:
if not self._validate_template(self._env, output):
if not isinstance(output, str):
raise ValueError(
f"Invalid template for output: {output!r} (type: {type(output).__name__}). "
f"Output must be a string representing a valid Jinja2 template. "
f"For example, use {str(output)!r} instead of {output!r}."
)
raise ValueError(f"Invalid template for output: {output}")
@staticmethod
def _extract_variables(env: Environment, templates: list[str]) -> set[str]:
"""
Extracts all variables from a list of Jinja template strings.
:param env: A Jinja environment.
:param templates: A list of Jinja template strings.
:returns: A set of variable names.
"""
variables = set()
for template in templates:
assigned_variables, template_variables = _extract_template_variables_and_assignments(View on GitHub (pinned to e318778c9b)
Solutions
- Make the route output a string, e.g. '{{ result }}' instead of the raw value
- Use the str() representation shown in the error message
- Set output_passthrough=True only if you intentionally want non-templated output
Example fix
# before
{"condition": "{{ ok }}", "output": 42, "output_name": "out", "output_type": int}
# after
{"condition": "{{ ok }}", "output": "{{ result }}", "output_name": "out", "output_type": int} Defensive patterns
Strategy: validation
Validate before calling
outputs = [r.get("output") for r in routes if not r.get("output_passthrough", False)]
assert all(isinstance(o, str) for o in outputs), "route output must be a Jinja2 template string" Type guard
def is_valid_output(output) -> bool:
return isinstance(output, str) Try / catch
try:
router = ConditionalRouter(routes=routes)
except ValueError as e:
if "Invalid template for output" in str(e):
routes = [{**r, "output": str(r["output"])} for r in routes if not r.get("output_passthrough", False)] + [r for r in routes if r.get("output_passthrough", False)]
router = ConditionalRouter(routes=routes)
else:
raise Prevention
- Keep route outputs as template strings even for simple values: '{{ result }}'
- Sanitize config-driven outputs with str() before constructing the router
- Use output_passthrough=True deliberately when output is not a template
When it happens
Trigger: Passing a non-string as route 'output', e.g. {'output': 42} or {'output': None}, while output_passthrough is False (default).
Common situations: Programmatic route construction where output is mistakenly a number or object; deserialized configs with wrong types.
Related errors
- Invalid template for condition: {condition_value}
- Invalid template for output: {output}
- The list of mime types cannot be empty.
- At least one of 'mime_type_meta_field' or 'file_path_meta_fi
- The list of mime types cannot be empty.
AI-assisted analysis of deepset-ai/haystack@e318778c9b (2026-08-30).
Data as JSON: /api/errors/820b5df40d14906b.
Report an issue: GitHub.