deepset-ai/haystack · error · RuntimeError

Tool ' ': failed to merge outputs into state.

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.

Solutions

  1. Read the chained cause (e) to see the underlying State error
  2. Add the missing key to the Agent's state_schema or fix the tool's output state_key
  3. 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

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


AI-assisted analysis of deepset-ai/haystack@e318778c9b (2026-08-30). Data as JSON: /api/errors/d4edcc27e9df51cb. Report an issue: GitHub.

Appendix: 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)