Skip to content
Merged
Show file tree
Hide file tree
Changes from 3 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
18 changes: 17 additions & 1 deletion haystack/components/routers/conditional_router.py
Original file line number Diff line number Diff line change
Expand Up @@ -398,10 +398,23 @@ def _validate_routes(self, routes: list[Route]):

# Validate templates
if not self._validate_template(self._env, route["condition"]):
raise ValueError(f"Invalid template for condition: {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}")

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
Expand Down Expand Up @@ -429,6 +442,9 @@ def _validate_template(self, env: Environment, template_text: str):
:param template_text: A Jinja template string.
:returns: `True` if the template is valid, `False` otherwise.
"""
# Check if template_text is a string before attempting to parse
if not isinstance(template_text, str):
return False
try:
env.parse(template_text)
return True
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
fixes:
- |
Improved error messages in ConditionalRouter when non-string values are provided as route outputs.
Users now receive clear guidance (e.g., "use '2' instead of 2") instead of the cryptic "Can't compile non template nodes" error.
41 changes: 41 additions & 0 deletions test/components/routers/test_conditional_router.py
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,47 @@ def test_invalid_condition_field(self):
with pytest.raises(ValueError, match="Invalid template"):
ConditionalRouter(routes)

def test_invalid_output_template_non_string(self):
"""
ConditionalRouter init raises a ValueError with helpful error message when output is not a string
"""
# output is an int instead of a string template
routes = [
{
"condition": '{{ flag == "double" }}',
"output": 2,
"output_name": "num_additional_outputs",
"output_type": int,
}
]
with pytest.raises(ValueError) as exc_info:
ConditionalRouter(routes)
error_message = str(exc_info.value)
assert "Invalid template for output" in error_message
assert "string" in error_message
assert "Jinja2 template" in error_message
assert "2" in error_message or "2!" in error_message
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm a little confused on this statement. When would 2! appear in the error message?


def test_invalid_output_template_non_string_list(self):
"""
ConditionalRouter init raises a ValueError with helpful error message when output in list is not a string
"""
# output list contains an int instead of a string template
routes = [
{
"condition": '{{ flag == "double" }}',
"output": ["{{streams}}", 2],
"output_name": ["streams", "num"],
"output_type": [list[int], int],
}
]
with pytest.raises(ValueError) as exc_info:
ConditionalRouter(routes)
error_message = str(exc_info.value)
assert "Invalid template for output" in error_message
assert "string" in error_message
assert "Jinja2 template" in error_message

def test_no_vars_in_output_route_but_with_output_name(self):
"""
Router can't accept a route with no variables used in the output field
Expand Down
Loading