deepset-ai/haystack · error · ValueError

Route output, output_type and output_name must have same len

Error message

Route output, output_type and output_name must have same length: {route}

What it means

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.

Source

Thrown at haystack/components/routers/conditional_router.py:508

                keys = set(route.keys())
            except AttributeError as e:
                raise ValueError(f"Route must be a dictionary, got: {route}") from e

            mandatory_fields = {"condition", "output", "output_type", "output_name"}
            has_all_mandatory_fields = mandatory_fields.issubset(keys)
            if not has_all_mandatory_fields:
                raise ValueError(
                    f"Route must contain 'condition', 'output', 'output_type' and 'output_name' fields: {route}"
                )

            # Validate outputs are consistent
            outputs = route["output"] if isinstance(route["output"], list) else [route["output"]]
            output_types = route["output_type"] if isinstance(route["output_type"], list) else [route["output_type"]]
            output_names = route["output_name"] if isinstance(route["output_name"], list) else [route["output_name"]]

            # Check lengths match
            if not len(outputs) == len(output_types) == len(output_names):
                raise ValueError(f"Route output, output_type and output_name must have same length: {route}")

            # 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):

View on GitHub (pinned to e318778c9b)

Solutions

  1. Make output, output_type, and output_name lists of the same length.
  2. If the route has one output, use scalar (non-list) values for all three fields.
  3. Recount the lists element-by-element after editing a multi-output route.

Example fix

// before
{"output": ["a", "b"], "output_type": [str], "output_name": ["x", "y"]}
// after
{"output": ["a", "b"], "output_type": [str, str], "output_name": ["x", "y"]}
Defensive patterns

Strategy: validation

Validate before calling

def norm(v): return v if isinstance(v, list) else [v]
for r in routes:
    lens = {len(norm(r["output"])), len(norm(r["output_type"])), len(norm(r["output_name"]))}
    assert lens == {norm(r["output"]).__len__()}, "output/output_type/output_name length mismatch"

Type guard

def output_lengths_match(route: dict) -> bool:
    n = lambda v: v if isinstance(v, list) else [v]
    return len(n(route["output"])) == len(n(route["output_type"])) == len(n(route["output_name"]))

Try / catch

try:
    router = ConditionalRouter(routes=routes)
except ValueError as e:
    if "must have same length" in str(e):
        routes = [pad_output_lists(r) for r in routes]
        router = ConditionalRouter(routes=routes)
    else:
        raise

Prevention

When it happens

Trigger: 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).

Common situations: 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.

Related errors


AI-assisted analysis of deepset-ai/haystack@e318778c9b (2026-08-30). Data as JSON: /api/errors/6e2fdd98430db121. Report an issue: GitHub.