AI & Agent Dev Bug Sandbox logo
AI & Agent Dev Bug Sandbox
Back to Radar

Parallel Tool Calls Without Index Collide On Positional Fallback Key And One Is Silently Dropped

In langchain-core's _compat_bridge._iter_protocol_blocks, tool_call content blocks lacking an explicit index are keyed by ("__lc_no_index__", block_type, position_in_chunk). When Gemini streams parallel function calls as separate chunks each containing one complete tool_call block at position 0, the keys collide. _accumulate then overwrites the earlier block with the later one, silently dropping the first tool call. This leads to incorrect model behavior and, with Gemini 3, the lost call may carry the thought_signature, causing upstream validation issues or silent execution of only one of the requested tools.

highConfidence 95%LangChainAffected V1.4.8Affected V1.6.2

Origin Analysis

The positional fallback key for content blocks without an index uses the block's position within its chunk. Since Gemini emits each parallel tool call in its own chunk with a single tool_call block at position 0, all such blocks receive the identical key ("__lc_no_index__", 'tool_call', 0). When these blocks are accumulated, the later block replaces the earlier one, causing data loss.
1. Import _accumulate and _iter_protocol_blocks from langchain_core.language_models._compat_bridge. 2. Create two AIMessageChunk objects, each containing one tool_call block with different ids (e.g., 'a' and 'b') and same type 'tool_call', no index. 3. Pass each through _iter_protocol_blocks to obtain (key, block_dict) tuples. 4. Observe that both keys are identical: ("__lc_no_index__", 'tool_call', 0). 5. Call _accumulate with the two block dictionaries; inspect the result: it will contain only the second call's id and name, proving the first was dropped.

Fixing Code Block

Edge Case Audit

This change assumes that tool_call blocks always carry a unique id when present. If a stream erroneously reuses the same id for two different calls, they will merge incorrectly. Additionally, if a provider fragments a single tool_call across multiple chunks and only some chunks include the id, the chunks without id will fall back to positional keying and may not merge with the id-keyed chunks, potentially breaking argument accumulation for such providers. Rollback recommendation: if this fix causes regressions with providers that stream tool_call arguments in fragments, revert to the original positional fallback and address the collision via a more comprehensive chunk-consolidation mechanism.

Ecosystem Topology