{"record":{"id":"b6a85bac0b8dcb56","repo":"deepset-ai/haystack","slug":"outputs-to-state-name-maps-state-key-state","errorCode":null,"errorMessage":"outputs_to_state: '{name}' maps state key '{state_key}' to unknown output '{source}'Valid outputs are: {valid_outputs}.","messagePattern":"outputs_to_state: '(.+?)' maps state key '(.+?)' to unknown output '(.+?)'Valid outputs are: (.+?)\\.","errorType":"validation","errorClass":"ValueError","httpStatus":null,"severity":"error","filePath":"haystack/tools/tool.py","lineNumber":153,"sourceCode":"            raise ValueError(\"The provided parameters do not define a valid JSON schema\") from e\n\n        # Validate outputs structure if provided\n        if self.outputs_to_state is not None:\n            for key, config in self.outputs_to_state.items():\n                if not isinstance(config, dict):\n                    raise TypeError(f\"outputs_to_state configuration for key '{key}' must be a dictionary\")\n                if \"source\" in config and not isinstance(config[\"source\"], str):\n                    raise ValueError(f\"outputs_to_state source for key '{key}' must be a string.\")\n                if \"handler\" in config and not callable(config[\"handler\"]):\n                    raise ValueError(f\"outputs_to_state handler for key '{key}' must be callable\")\n\n            # Validate that outputs_to_state source keys exist as valid tool outputs\n            valid_outputs: set[str] | None = self._get_valid_outputs()\n            if valid_outputs is not None:\n                for state_key, config in self.outputs_to_state.items():\n                    source = config.get(\"source\")\n                    if source is not None and source not in valid_outputs:\n                        raise ValueError(\n                            f\"outputs_to_state: '{self.name}' maps state key '{state_key}' to unknown output '{source}'\"\n                            f\"Valid outputs are: {valid_outputs}.\"\n                        )\n\n        if self.outputs_to_string is not None:\n            if \"source\" in self.outputs_to_string and not isinstance(self.outputs_to_string[\"source\"], str):\n                raise ValueError(\"outputs_to_string source must be a string.\")\n            if \"handler\" in self.outputs_to_string and not callable(self.outputs_to_string[\"handler\"]):\n                raise ValueError(\"outputs_to_string handler must be callable\")\n            if \"raw_result\" in self.outputs_to_string and not isinstance(self.outputs_to_string[\"raw_result\"], bool):\n                raise ValueError(\"outputs_to_string raw_result must be a boolean.\")\n\n            if (\n                \"source\" in self.outputs_to_string\n                or \"handler\" in self.outputs_to_string\n                or \"raw_result\" in self.outputs_to_string\n            ):\n                # Single output configuration","sourceCodeStart":135,"sourceCodeEnd":171,"githubUrl":"https://github.com/deepset-ai/haystack/blob/e318778c9bf60a1963e3b5f451359655dd696c30/haystack/tools/tool.py#L135-L171","documentation":"outputs_to_state entries with a \"source\" must reference an output the tool actually produces. __post_init__ computes the set of valid outputs (from the function signature/outputs) and raises ValueError when a source name is unknown, listing the valid outputs.","triggerScenarios":"Tool(..., outputs_to_state={\"k\": {\"source\": \"results\"}}) while the tool function is declared to produce outputs like [\"documents\", \"answer\"] — any typo'd or stale output name.","commonSituations":"Renaming a tool's outputs (or changing the decorated function's return signature) without updating outputs_to_state; copy-pasting configs between similar tools; mixing up parameter names with output names.","solutions":["Change \"source\" to one of the listed valid outputs in the error message.","Update the tool function's declared outputs to include the referenced name if that output is intended.","Run the Tool construction in a test so the mismatch fails fast at init rather than at pipeline runtime."],"exampleFix":"// before\nTool(name=\"retriever\", function=retrieve, outputs_to_state={\"k\": {\"source\": \"results\"}})\n\n// after\nTool(name=\"retriever\", function=retrieve, outputs_to_state={\"k\": {\"source\": \"documents\"}})  # valid output","handlingStrategy":"validation","validationCode":"valid = {\"documents\", \"answer\"}  # tool's declared outputs\nfor k, cfg in outputs_to_state.items():\n    src = cfg.get(\"source\")\n    assert src is None or src in valid, f\"'{src}' not in tool outputs {valid}\"","typeGuard":null,"tryCatchPattern":"try:\n    tool = Tool(name=\"t\", function=f, outputs_to_state=ots)\nexcept ValueError as e:\n    if \"unknown output\" in str(e):\n        logger.error(e)  # message lists the valid outputs\n    raise","preventionTips":["Read the valid outputs from the error message and align source names","Update outputs_to_state whenever a tool function's outputs change","Add a test constructing every Tool so renames fail fast"],"tags":["python","tool","config","validation"],"backgroundTag":"unknown-output-name","analyzedSha":"e318778c9bf60a1963e3b5f451359655dd696c30","analyzedAt":"2026-08-30T11:45:20.711Z","schemaVersion":2},"datasetVersion":"2026-08-30T13:17:10.514Z"}