{"record":{"id":"9345203ac74a6c3f","repo":"deepset-ai/haystack","slug":"variable-output-not-found-in-inputs-for-passth","errorCode":null,"errorMessage":"Variable '{output}' not found in inputs for passthrough route '{output_name}'. Ensure '{output}' is passed as an input to the router.","messagePattern":"Variable '(.+?)' not found in inputs for passthrough route '(.+?)'\\. Ensure '(.+?)' is passed as an input to the router\\.","errorType":"exception","errorClass":"ValueError","httpStatus":null,"severity":"error","filePath":"haystack/components/routers/conditional_router.py","lineNumber":447,"sourceCode":"                if not rendered:\n                    continue\n\n                # Handle multiple outputs\n                outputs = route[\"output\"] if isinstance(route[\"output\"], list) else [route[\"output\"]]\n                output_types = (\n                    route[\"output_type\"] if isinstance(route[\"output_type\"], list) else [route[\"output_type\"]]\n                )\n                output_names = (\n                    route[\"output_name\"] if isinstance(route[\"output_name\"], list) else [route[\"output_name\"]]\n                )\n                output_passthrough = route.get(\"output_passthrough\", False)\n\n                result = {}\n                for output, output_type, output_name in zip(outputs, output_types, output_names, strict=True):\n                    if output_passthrough:\n                        # output is a plain variable name — retrieve directly from kwargs, no Jinja2 processing\n                        if output not in kwargs:\n                            raise ValueError(  # noqa: TRY301\n                                f\"Variable '{output}' not found in inputs for passthrough route '{output_name}'. \"\n                                f\"Ensure '{output}' is passed as an input to the router.\"\n                            )\n                        output_value = kwargs[output]\n                    else:\n                        # Standard Jinja2 template evaluation\n                        t_output = self._env.from_string(output)\n                        output_value = t_output.render(**kwargs)\n\n                        # We suppress the exception in case the output is already a string, otherwise\n                        # we try to evaluate it and would fail.\n                        # This must be done cause the output could be different literal structures.\n                        # This doesn't support any user types.\n                        with contextlib.suppress(Exception):\n                            if not self._unsafe:\n                                output_value = ast.literal_eval(output_value)\n\n                    # Validate output type if needed","sourceCodeStart":429,"sourceCodeEnd":465,"githubUrl":"https://github.com/deepset-ai/haystack/blob/e318778c9bf60a1963e3b5f451359655dd696c30/haystack/components/routers/conditional_router.py#L429-L465","documentation":"The matched route has output_passthrough=True, so `output` is treated as a plain variable name looked up directly in the router's kwargs instead of being rendered as a Jinja template. The named variable was not among the run() inputs, so a ValueError is raised identifying the missing variable and output_name.","triggerScenarios":"Running ConditionalRouter.run() (or running a pipeline where the router receives connections) when the first fired route uses output_passthrough and its `output` variable name is absent from the router's inputs.","commonSituations":"Renaming an upstream component's output so the router no longer receives the variable; wiring a pipeline without connecting the variable the passthrough route expects; hand-written routes where output was edited but inputs weren't updated.","solutions":["Pass the variable named in the error to run() (e.g. router.run(query=...)).","Fix the route's `output` to name a variable actually supplied to the router.","Fix the pipeline wiring so the upstream output connects to the router input with that name.","Set output_passthrough=False if you want `output` treated as a Jinja template instead of a plain variable name."],"exampleFix":"// before\nresult = router.run()  # route output='query', passthrough\n// after\nresult = router.run(query=question_text)","handlingStrategy":"validation","validationCode":"passthrough_outputs = [o for r in router.routes if r.get(\"output_passthrough\")\n                       for o in (r[\"output\"] if isinstance(r[\"output\"], list) else [r[\"output\"]])]\nmissing = [o for o in passthrough_outputs if o not in kwargs]\nassert not missing, f\"router inputs missing: {missing}\"","typeGuard":"def passthrough_inputs_satisfied(router, kwargs: dict) -> bool:\n    return all(o in kwargs\n               for r in router.routes if r.get(\"output_passthrough\")\n               for o in (r[\"output\"] if isinstance(r[\"output\"], list) else [r[\"output\"]]))","tryCatchPattern":"try:\n    result = router.run(**kwargs)\nexcept ValueError as e:\n    if \"not found in inputs for passthrough route\" in str(e):\n        kwargs.update(required_passthrough_vars)\n        result = router.run(**kwargs)\n    else:\n        raise","preventionTips":["Connect every variable named in passthrough route outputs as a router input.","After renaming upstream outputs, update the route's `output` names too.","Unit-test the router standalone with representative kwargs before wiring into a pipeline."],"tags":["router","missing-variable","pipeline-wiring"],"backgroundTag":"missing-input-variable","analyzedSha":"e318778c9bf60a1963e3b5f451359655dd696c30","analyzedAt":"2026-08-30T11:45:20.711Z","schemaVersion":2},"datasetVersion":"2026-08-30T13:17:10.514Z"}