deepset-ai/haystack · error · RuntimeError
Tool '{tool.name}': failed to merge outputs into state. {e}
Error message
Tool '{tool.name}': failed to merge outputs into state. {e} What it means
_merge_tool_outputs_into_state wraps any exception from State.set in this RuntimeError, chained with the original cause. It signals that a tool's output could not be merged into agent state — typically because the target state key is not in the schema or the handler failed.
Source
Thrown at haystack/components/agents/tool_calling.py:80
def _merge_tool_outputs_into_state(tool: Tool, result: Any, state: State) -> None:
"""
Write tool outputs into State according to the tool's `outputs_to_state` mapping.
:raises RuntimeError: If writing an output value into the state fails.
"""
if not isinstance(result, dict):
return
for state_key, config in (tool.outputs_to_state or {}).items():
source_key = config.get("source", None)
if source_key and source_key not in result:
continue
output_value = result.get(source_key) if source_key else result
try:
state.set(state_key, output_value, handler_override=config.get("handler"))
except Exception as e:
raise RuntimeError(f"Tool '{tool.name}': failed to merge outputs into state. {e}") from e
def _result_to_string(result: Any) -> str:
"""
Convert a tool result to a string.
Strings are returned as-is; all other types are passed through a JSON serialization step to produce more readable
output, with a fallback to plain str() conversion if serialization fails.
:param result: The tool result to convert.
:returns: A string representation of the tool result.
"""
if isinstance(result, str):
return result
serializable = _serializable_value(value=result, use_placeholders=False)
try:
return json.dumps(serializable, ensure_ascii=False)
except Exception as error:View on GitHub (pinned to e318778c9b)
Solutions
- Read the chained cause (e) to see the underlying State error
- Add the missing key to the Agent's state_schema or fix the tool's output state_key
- Test the custom handler against the tool's actual output shape
Example fix
// before
tool = Tool(..., outputs_to_state={"summary": {"source_key": "sum"}})
# state_schema lacks "summary"
// after
agent = Agent(..., state_schema={..., "summary": {"type": str}}) Defensive patterns
Strategy: try-catch
Validate before calling
def output_keys_declared(tool, schema):
for state_key in tool.outputs_to_state or {}:
if state_key not in schema:
raise ValueError(f"State key '{state_key}' missing from schema") Type guard
def can_merge(tool, schema) -> bool:
return all(k in schema for k in (tool.outputs_to_state or {})) Try / catch
try:
finalize_tool_result(tool, result, state, config)
except RuntimeError as e:
if "failed to merge outputs into state" in str(e):
logging.warning("State merge failed for %s: %s", tool.name, e.__cause__)
# fall back to returning tool output as string only
else:
raise Prevention
- Inspect e.__cause__ to find the real State error
- Keep outputs_to_state mappings and state_schema definitions in one place
- Unit-test each tool's merge path against the real schema
- Validate custom handlers against actual tool output shapes
When it happens
Trigger: A tool's output mapping references a state_key absent from the schema (inner ValueError), or the configured handler raises inside state.set.
Common situations: Mismatch between tool output config and Agent state_schema after refactoring; a custom handler raising on unexpected value shapes.
Related errors
- tools must be a list of Tool and/or Toolset objects, a Tools
- StateSchema: Key '{param}' is missing a 'type' entry.
- StateSchema: 'type' for key '{param}' must be a Python type,
- StateSchema: 'handler' for key '{param}' must be callable or
- StateSchema: 'messages' must be of type list[ChatMessage], g
AI-assisted analysis of deepset-ai/haystack@e318778c9b (2026-08-30).
Data as JSON: /api/errors/d4edcc27e9df51cb.
Report an issue: GitHub.