Skip to content

fix: prevent None corruption in agent state when outputs_to_state source key is absent#10987

Closed
IgnazioDS wants to merge 2 commits intodeepset-ai:mainfrom
IgnazioDS:fix/outputs-to-state-none-corruption
Closed

fix: prevent None corruption in agent state when outputs_to_state source key is absent#10987
IgnazioDS wants to merge 2 commits intodeepset-ai:mainfrom
IgnazioDS:fix/outputs-to-state-none-corruption

Conversation

@IgnazioDS
Copy link
Copy Markdown

Summary

Fixes #10981.

When a tool's result dict does not contain a key referenced by outputs_to_state, result.get(source_key) silently returns None. That None then flows into state.set(), and when the state field uses the merge_lists handler it gets wrapped into [None], corrupting the state list with a spurious None entry.

Root cause (two layers)

  1. _merge_tool_outputs (haystack/components/tools/tool_invoker.py) — no guard on output_value is None before calling state.set().
  2. merge_lists (haystack/components/agents/state/state_utils.py) — new if isinstance(new, list) else [new] wraps None into [None] instead of treating absent output as a no-op.

Fix

tool_invoker.py — skip state.set() when the tool didn't produce the mapped output:

output_value = result.get(source_key) if source_key else result
# Skip state update when the tool didn't produce this output key
if output_value is None:
    continue
state.set(state_key, output_value, handler_override=config.get("handler"))

state_utils.py — treat None as "nothing to merge":

if new is None:
    return current_list

Both layers are needed: the tool_invoker fix is the primary guard; the merge_lists fix makes the function robust as a standalone utility.

Test plan

  • Reproduce with a tool whose outputs_to_state maps a key that may be absent from the result dict — confirm state no longer contains None entries
  • Existing merge_lists tests pass
  • merge_lists(["a"], None) returns ["a"] (not ["a", None])
  • merge_lists(None, None) returns []

@IgnazioDS IgnazioDS requested a review from a team as a code owner March 30, 2026 18:23
@IgnazioDS IgnazioDS requested review from julian-risch and removed request for a team March 30, 2026 18:23
@vercel
Copy link
Copy Markdown

vercel Bot commented Mar 30, 2026

@IgnazioDS is attempting to deploy a commit to the deepset Team on Vercel.

A member of the Team first needs to authorize it.

@CLAassistant
Copy link
Copy Markdown

CLA assistant check
Thank you for your submission! We really appreciate it. Like many open source projects, we ask that you sign our Contributor License Agreement before we can accept your contribution.
You have signed the CLA already but the status is still pending? Let us recheck it.

@github-actions github-actions Bot added the type:documentation Improvements on the docs label Mar 30, 2026
@sjrl
Copy link
Copy Markdown
Contributor

sjrl commented Mar 31, 2026

@IgnazioDS thanks for jumping on this so quickly, but this was an issue we wanted to handle internally and did so in this PR #10990 so I'll be closing this PR

@sjrl sjrl closed this Mar 31, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

type:documentation Improvements on the docs

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Agent state corrupted with None entries when outputs_to_state source key absent from tool result

3 participants