From e1f3befa761ccb6d79dcc86d412b1618385131db Mon Sep 17 00:00:00 2001 From: Nilesh Patil <128893479+nileshpatil6@users.noreply.github.com> Date: Tue, 21 Apr 2026 00:57:32 +0530 Subject: [PATCH] fix: merge server_side_tool_invocations by id in stream_chunk_builder The naive last-wins merge for list-type provider_specific_fields caused Gemini streaming to corrupt server_side_tool_invocations and thought_signatures. Replace with merge-by-id for tool invocations (first-wins per key, filling None values from later chunks) and accumulate thought_signatures across chunks. Fixes #25869 --- litellm/main.py | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/litellm/main.py b/litellm/main.py index ddd37b47536..fdac5d933ec 100644 --- a/litellm/main.py +++ b/litellm/main.py @@ -7604,6 +7604,19 @@ def stream_chunk_builder( # noqa: PLR0915 for key, value in fields.items(): if key not in combined_provider_fields: combined_provider_fields[key] = value + elif key == "server_side_tool_invocations" and isinstance(value, list): + existing = {e.get("id", ""): e for e in combined_provider_fields[key]} + for inv in value: + inv_id = inv.get("id", "") + if inv_id in existing: + for k, v in inv.items(): + if v is not None and (k not in existing[inv_id] or existing[inv_id][k] is None): + existing[inv_id][k] = v + else: + existing[inv_id] = dict(inv) + combined_provider_fields[key] = list(existing.values()) + elif key == "thought_signatures" and isinstance(value, list): + combined_provider_fields[key] = combined_provider_fields[key] + value elif isinstance(value, list) and isinstance( combined_provider_fields[key], list ):