{"record":{"id":"45940184ef591be4","repo":"deepset-ai/haystack","slug":"invalid-template-for-condition-condition-value-r","errorCode":null,"errorMessage":"Invalid template for condition: {condition_value!r} (type: {type(condition_value).__name__}).Condition must be a string representing a valid Jinja2 template. For example, use {str(condition_value)!r} instead of {condition_value!r}.","messagePattern":"Invalid template for condition: (.+?) \\(type: (.+?)\\)\\.Condition must be a string representing a valid Jinja2 template\\. For example, use (.+?) instead of (.+?)\\.","errorType":"validation","errorClass":"ValueError","httpStatus":null,"severity":"error","filePath":"haystack/components/routers/conditional_router.py","lineNumber":514,"sourceCode":"            if not has_all_mandatory_fields:\n                raise ValueError(\n                    f\"Route must contain 'condition', 'output', 'output_type' and 'output_name' fields: {route}\"\n                )\n\n            # Validate outputs are consistent\n            outputs = route[\"output\"] if isinstance(route[\"output\"], list) else [route[\"output\"]]\n            output_types = route[\"output_type\"] if isinstance(route[\"output_type\"], list) else [route[\"output_type\"]]\n            output_names = route[\"output_name\"] if isinstance(route[\"output_name\"], list) else [route[\"output_name\"]]\n\n            # Check lengths match\n            if not len(outputs) == len(output_types) == len(output_names):\n                raise ValueError(f\"Route output, output_type and output_name must have same length: {route}\")\n\n            # Condition is always a Jinja2 template — validate it\n            if not self._validate_template(self._env, route[\"condition\"]):\n                condition_value = route[\"condition\"]\n                if not isinstance(condition_value, str):\n                    raise ValueError(\n                        f\"Invalid template for condition: {condition_value!r} (type: {type(condition_value).__name__}).\"\n                        f\"Condition must be a string representing a valid Jinja2 template. \"\n                        f\"For example, use {str(condition_value)!r} instead of {condition_value!r}.\"\n                    )\n                raise ValueError(f\"Invalid template for condition: {condition_value}\")\n\n            # Only validate output as Jinja2 template when output_passthrough is False (default)\n            output_passthrough = route.get(\"output_passthrough\", False)\n            if not output_passthrough:\n                for output in outputs:\n                    if not self._validate_template(self._env, output):\n                        if not isinstance(output, str):\n                            raise ValueError(\n                                f\"Invalid template for output: {output!r} (type: {type(output).__name__}). \"\n                                f\"Output must be a string representing a valid Jinja2 template. \"\n                                f\"For example, use {str(output)!r} instead of {output!r}.\"\n                            )\n                        raise ValueError(f\"Invalid template for output: {output}\")","sourceCodeStart":496,"sourceCodeEnd":532,"githubUrl":"https://github.com/deepset-ai/haystack/blob/e318778c9bf60a1963e3b5f451359655dd696c30/haystack/components/routers/conditional_router.py#L496-L532","documentation":"The route's condition failed Jinja template validation. If the condition is not even a string, this detailed ValueError names the actual type and hints that a string was expected; a string condition with invalid Jinja syntax gets the simpler message variant. This surfaces at ConditionalRouter construction via _validate_routes.","triggerScenarios":"Passing a non-string condition (e.g. a lambda, bool, or int) in a route dict, or a string condition that fails _validate_template (invalid Jinja2 syntax) when constructing ConditionalRouter.","commonSituations":"Confusing route conditions with callable predicates (from other router APIs); accidental dict/int in YAML for the condition field; Jinja syntax errors like unbalanced {% %} or a stray filter pipe in condition strings.","solutions":["Convert the condition to a string: str(condition) or quote it in YAML.","Fix Jinja2 syntax errors in the condition string (test with jinja2 Environment.from_string).","If you intended function-based routing, express the logic as a Jinja expression instead of a callable.","Validate all conditions with the router's environment before constructing it."],"exampleFix":"// before\n{\"condition\": lambda q: q == \"a\", ...}\n// after\n{\"condition\": \"query == 'a'\", ...}","handlingStrategy":"validation","validationCode":"import jinja2\nenv = jinja2.Environment()\nfor r in routes:\n    assert isinstance(r[\"condition\"], str), f\"condition must be str, got {type(r['condition']).__name__}\"\n    env.parse(r[\"condition\"])  # raises TemplateSyntaxError on bad Jinja","typeGuard":"def is_valid_condition(value) -> bool:\n    import jinja2\n    if not isinstance(value, str):\n        return False\n    try:\n        jinja2.Environment().parse(value)\n        return True\n    except jinja2.TemplateSyntaxError:\n        return False","tryCatchPattern":"try:\n    router = ConditionalRouter(routes=routes)\nexcept ValueError as e:\n    if str(e).startswith(\"Invalid template for condition\"):\n        routes = [{**r, \"condition\": str(r[\"condition\"])} if not isinstance(r[\"condition\"], str) else r\n                  for r in routes]\n        router = ConditionalRouter(routes=routes)\n    else:\n        raise","preventionTips":["Keep conditions as Jinja string expressions; never pass callables or raw Python objects.","Quote condition strings in YAML to avoid type coercion (e.g. 'on' becoming bool True).","Pre-parse conditions with jinja2 in tests before constructing routers."],"tags":["router","jinja","validation","type-mismatch"],"backgroundTag":"invalid-jinja-template","analyzedSha":"e318778c9bf60a1963e3b5f451359655dd696c30","analyzedAt":"2026-08-30T11:45:20.711Z","schemaVersion":2},"datasetVersion":"2026-08-30T13:17:10.514Z"}