deepset-ai/haystack · error · ValueError
outputs_to_state source for key '{key}' must be a string.
Error message
outputs_to_state source for key '{key}' must be a string. What it means
When an outputs_to_state entry includes a "source" key, its value must be a string naming the tool output to read. __post_init__ raises ValueError when config["source"] is present but not a str (e.g. a list, int, or None explicitly passed).
Source
Thrown at haystack/tools/tool.py:143
if self.async_function is not None and not inspect.iscoroutinefunction(self.async_function):
raise ValueError(
f"`async_function` must be a coroutine function defined with `async def`. "
f"Got '{getattr(self.async_function, '__name__', repr(self.async_function))}'."
)
# Check that the parameters define a valid JSON schema
try:
Draft202012Validator.check_schema(self.parameters)
except SchemaError as e:
raise ValueError("The provided parameters do not define a valid JSON schema") from e
# Validate outputs structure if provided
if self.outputs_to_state is not None:
for key, config in self.outputs_to_state.items():
if not isinstance(config, dict):
raise TypeError(f"outputs_to_state configuration for key '{key}' must be a dictionary")
if "source" in config and not isinstance(config["source"], str):
raise ValueError(f"outputs_to_state source for key '{key}' must be a string.")
if "handler" in config and not callable(config["handler"]):
raise ValueError(f"outputs_to_state handler for key '{key}' must be callable")
# Validate that outputs_to_state source keys exist as valid tool outputs
valid_outputs: set[str] | None = self._get_valid_outputs()
if valid_outputs is not None:
for state_key, config in self.outputs_to_state.items():
source = config.get("source")
if source is not None and source not in valid_outputs:
raise ValueError(
f"outputs_to_state: '{self.name}' maps state key '{state_key}' to unknown output '{source}'"
f"Valid outputs are: {valid_outputs}."
)
if self.outputs_to_string is not None:
if "source" in self.outputs_to_string and not isinstance(self.outputs_to_string["source"], str):
raise ValueError("outputs_to_string source must be a string.")
if "handler" in self.outputs_to_string and not callable(self.outputs_to_string["handler"]):View on GitHub (pinned to e318778c9b)
Solutions
- Set "source" to the exact string name of one tool output: {"k": {"source": "documents"}}.
- To map multiple outputs, create one entry per output/state key rather than a list source.
- Omit "source" entirely if the whole tool result should feed the state key.
Example fix
// before
outputs_to_state={"k": {"source": ["doc", "answer"]}}
// after
outputs_to_state={"docs": {"source": "doc"}, "ans": {"source": "answer"}} Defensive patterns
Strategy: type-guard
Validate before calling
for k, cfg in outputs_to_state.items():
if "source" in cfg and not isinstance(cfg["source"], str):
raise TypeError(f"source for '{k}' must be a string") Type guard
def has_valid_sources(ots: dict) -> bool:
return all(isinstance(c.get("source", ""), str) for c in ots.values()) Try / catch
try:
tool = Tool(name="t", function=f, outputs_to_state=ots)
except ValueError as e:
if "source" in str(e):
logger.error(f"Fix outputs_to_state source types: {e}")
raise Prevention
- Store source names as plain strings, one output per entry
- Don't pass lists of outputs as a single source
- Validate configs loaded from YAML/JSON for types before constructing Tools
When it happens
Trigger: Tool(..., outputs_to_state={"k": {"source": 42}}) or {"k": {"source": ["out1", "out2"]}} — a non-string source value.
Common situations: Confusing source with the state-key mapping of multiple outputs; programmatically generated configs where the source is a list of outputs; typos yielding a non-str default value.
Related errors
- outputs_to_state: '{name}' maps state key '{state_key}' to u
- outputs_to_string source must be a string.
- Invalid outputs_to_string config. When using 'source', 'hand
- top_k must be greater than 0.
- `async_function` must be a coroutine function defined with `
AI-assisted analysis of deepset-ai/haystack@e318778c9b (2026-08-30).
Data as JSON: /api/errors/fa8cec00921cbf47.
Report an issue: GitHub.