{"record":{"id":"6e2fdd98430db121","repo":"deepset-ai/haystack","slug":"route-output-output-type-and-output-name-must-hav","errorCode":null,"errorMessage":"Route output, output_type and output_name must have same length: {route}","messagePattern":"Route output, output_type and output_name must have same length: (.+?)","errorType":"validation","errorClass":"ValueError","httpStatus":null,"severity":"error","filePath":"haystack/components/routers/conditional_router.py","lineNumber":508,"sourceCode":"                keys = set(route.keys())\n            except AttributeError as e:\n                raise ValueError(f\"Route must be a dictionary, got: {route}\") from e\n\n            mandatory_fields = {\"condition\", \"output\", \"output_type\", \"output_name\"}\n            has_all_mandatory_fields = mandatory_fields.issubset(keys)\n            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):","sourceCodeStart":490,"sourceCodeEnd":526,"githubUrl":"https://github.com/deepset-ai/haystack/blob/e318778c9bf60a1963e3b5f451359655dd696c30/haystack/components/routers/conditional_router.py#L490-L526","documentation":"When a route uses multiple outputs, output, output_type, and output_name may each be a list; _validate_routes requires all three lists to have equal length so outputs pair up via strict zip at run time. Unequal lengths raise ValueError at construction.","triggerScenarios":"A route dict where output, output_type, or output_name is a list and the three lists differ in length (e.g. 2 outputs, 3 output_names).","commonSituations":"Multi-output routes where a new output was appended to `output` but not to output_type/output_name; YAML list indentation mistakes producing wrong-length lists.","solutions":["Make output, output_type, and output_name lists of the same length.","If the route has one output, use scalar (non-list) values for all three fields.","Recount the lists element-by-element after editing a multi-output route."],"exampleFix":"// before\n{\"output\": [\"a\", \"b\"], \"output_type\": [str], \"output_name\": [\"x\", \"y\"]}\n// after\n{\"output\": [\"a\", \"b\"], \"output_type\": [str, str], \"output_name\": [\"x\", \"y\"]}","handlingStrategy":"validation","validationCode":"def norm(v): return v if isinstance(v, list) else [v]\nfor r in routes:\n    lens = {len(norm(r[\"output\"])), len(norm(r[\"output_type\"])), len(norm(r[\"output_name\"]))}\n    assert lens == {norm(r[\"output\"]).__len__()}, \"output/output_type/output_name length mismatch\"","typeGuard":"def output_lengths_match(route: dict) -> bool:\n    n = lambda v: v if isinstance(v, list) else [v]\n    return len(n(route[\"output\"])) == len(n(route[\"output_type\"])) == len(n(route[\"output_name\"]))","tryCatchPattern":"try:\n    router = ConditionalRouter(routes=routes)\nexcept ValueError as e:\n    if \"must have same length\" in str(e):\n        routes = [pad_output_lists(r) for r in routes]\n        router = ConditionalRouter(routes=routes)\n    else:\n        raise","preventionTips":["Edit multi-output routes' three lists together, never one in isolation.","Write a small lint that checks output/output_type/output_name list lengths in pipeline YAML.","Prefer scalar values for single-output routes to avoid list-length pitfalls."],"tags":["router","validation","multi-output"],"backgroundTag":"invalid-route-config","analyzedSha":"e318778c9bf60a1963e3b5f451359655dd696c30","analyzedAt":"2026-08-30T11:45:20.711Z","schemaVersion":2},"datasetVersion":"2026-08-30T13:17:10.514Z"}