deepset-ai/haystack · error · ValueError
Invalid outputs_to_string config. When using 'source', 'hand
Error message
Invalid outputs_to_string config. When using 'source', 'handler' or 'raw_result' at the root level, no other keys are allowed. Use individual output configs instead.
What it means
outputs_to_string supports two shapes: a single-output config whose keys are only source/handler/raw_result, or a per-output config keyed by output names. Mixing them — root-level source/handler/raw_result alongside any other key — is rejected with this ValueError at Tool construction.
Source
Thrown at haystack/tools/tool.py:174
)
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"]):
raise ValueError("outputs_to_string handler must be callable")
if "raw_result" in self.outputs_to_string and not isinstance(self.outputs_to_string["raw_result"], bool):
raise ValueError("outputs_to_string raw_result must be a boolean.")
if (
"source" in self.outputs_to_string
or "handler" in self.outputs_to_string
or "raw_result" in self.outputs_to_string
):
# Single output configuration
for key in self.outputs_to_string:
if key not in {"source", "handler", "raw_result"}:
raise ValueError(
"Invalid outputs_to_string config. "
"When using 'source', 'handler' or 'raw_result' at the root level, no other keys are "
" allowed. Use individual output configs instead."
)
else:
# Multiple outputs configuration
for key, config in self.outputs_to_string.items():
if not isinstance(config, dict):
raise TypeError(f"outputs_to_string configuration for key '{key}' must be a dictionary")
if "raw_result" in config:
raise ValueError(
f"Invalid outputs_to_string configuration for key '{key}': "
f"'raw_result' is not supported in the multiple output format."
)
if "source" not in config:
raise ValueError(
f"Invalid outputs_to_string configuration for key '{key}': "
f"each output must have a 'source' defined."View on GitHub (pinned to e318778c9b)
Solutions
- Use one output-name key per entry with no root-level keys: {"answer": {"handler": fn}} instead of {"source": "answer", "handler": fn} mixed with others.
- If one output needs config and others don't, give each output its own (possibly empty) dict.
- Split into two configs only if using two separate Tools; a single Tool must use a uniform shape.
Example fix
// before
outputs_to_string={"source": "answer", "handler": fmt, "documents": {"handler": doc_fmt}}
// after
outputs_to_string={"answer": {"handler": fmt}, "documents": {"handler": doc_fmt}} Defensive patterns
Strategy: validation
Validate before calling
ots = outputs_to_string or {}
ROOT_KEYS = {"source", "handler", "raw_result"}
if (ROOT_KEYS & ots.keys()) and (ots.keys() - ROOT_KEYS):
raise ValueError("outputs_to_string mixes root-level keys with per-output configs") Type guard
def is_uniform_outputs_to_string(ots: dict | None) -> bool:
if ots is None:
return True
ROOT = {"source", "handler", "raw_result"}
return not (ROOT & ots.keys()) or not (ots.keys() - ROOT) Try / catch
try:
tool = Tool(name="t", function=f, outputs_to_string=ots)
except ValueError as e:
if "Invalid outputs_to_string" in str(e):
ots = {k: (v if isinstance(v, dict) else {k2: v for k2 in ("source", "handler", "raw_result") if k2 == k} or {}) for k, v in [("answer", ots)]}
raise Prevention
- Pick one shape: per-output keys only, or root-level keys only
- Don't merge single-output and multi-output configs with dict update
- Validate the mixed-key condition in tests before constructing Tools
When it happens
Trigger: Tool(..., outputs_to_string={"source": "answer", "documents": {"handler": fn}}) — a root-level key plus an output-name key; or {"raw_result": True, "foo": {...}}.
Common situations: Merging two configs (one single-output, one multi-output) with dict update; incremental edits adding a per-output entry to an existing single-output config.
Related errors
- outputs_to_state source for key '{key}' must be a string.
- outputs_to_state: '{name}' maps state key '{state_key}' to u
- outputs_to_string source must be a string.
- 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/f1c49b69a3e22140.
Report an issue: GitHub.