deepset-ai/haystack · error · ValueError

Route must contain 'condition', 'output', 'output_type' and

Error message

Route must contain 'condition', 'output', 'output_type' and 'output_name' fields: {route}

What it means

Each route dict must define all four mandatory fields: condition, output, output_type, and output_name. _validate_routes (called from __init__) raises ValueError when any of these keys is missing from a route.

Source

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

        raise NoRouteSelectedException(f"No route fired. Routes: {self.routes}")

    def _validate_routes(self, routes: list[Route]) -> None:
        """
        Validates a list of routes.

        :param routes: A list of routes.
        """
        for route in routes:
            try:
                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__})."

View on GitHub (pinned to e318778c9b)

Solutions

  1. Add the missing field(s) named in the mandatory set to each route dict.
  2. Validate your route dicts against the required keys before constructing the router.
  3. If migrating from older configs, add output_name/output_type which newer versions require.

Example fix

// before
{"condition": "x > 1", "output": "out"}
// after
{"condition": "x > 1", "output": "out", "output_type": str, "output_name": "out"}
Defensive patterns

Strategy: validation

Validate before calling

REQUIRED = {"condition", "output", "output_type", "output_name"}
for i, r in enumerate(routes):
    missing = REQUIRED - set(r.keys())
    assert not missing, f"route {i} missing fields: {missing}"

Type guard

from typing import TypedDict
class Route(TypedDict):
    condition: str
    output: str | list
    output_type: type | list
    output_name: str | list

def routes_conform(routes) -> bool:
    return all(set(r.keys()) >= {"condition", "output", "output_type", "output_name"} for r in routes)

Try / catch

try:
    router = ConditionalRouter(routes=routes)
except ValueError as e:
    if "must contain 'condition'" in str(e):
        routes = [fill_defaults(r) for r in routes]
        router = ConditionalRouter(routes=routes)
    else:
        raise

Prevention

When it happens

Trigger: ConditionalRouter(routes=[...]) with a route dict missing one or more of condition/output/output_type/output_name.

Common situations: Copying example routes and deleting fields; hand-written YAML omitting output_name or output_type; refactors that rename keys without updating all routes.

Related errors


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