langchain-ai/deepagents · error · ValueError
Auto mode rejects action batches with duplicate tool-call ID
Error message
Auto mode rejects action batches with duplicate tool-call IDs
What it means
Raised by `_validate_unique_tool_call_ids` when a model proposes an action batch containing two or more tool calls with the same `id`. Auto mode needs unique IDs to correlate each proposed action with its own human decision and result message, so it rejects the whole batch.
Source
Thrown at libs/code/deepagents_code/auto_mode.py:1654
Returns:
Valid identifier used for plans and decisions.
Raises:
ValueError: If the model omitted a stable identifier.
"""
value = call.get("id")
if not isinstance(value, str) or not value:
msg = "Auto mode requires every proposed tool call to have an ID"
raise ValueError(msg)
return value
def _validate_unique_tool_call_ids(calls: Sequence[ToolCall]) -> None:
ids = [_tool_call_id(call) for call in calls]
if len(ids) != len(set(ids)):
msg = "Auto mode rejects action batches with duplicate tool-call IDs"
raise ValueError(msg)
def _batch_id(calls: Sequence[ToolCall]) -> str:
encoded = "\0".join(_tool_call_id(call) for call in calls).encode("utf-8")
return sha256(encoded).hexdigest()
def _review_tool_call_ids(
raw_plan: object,
valid_tool_call_ids: Collection[str],
) -> list[str]:
"""Return the reviewed tool-call IDs a checkpointed plan still covers.
These IDs only pause and resume tool rows in the client, so a malformed
value degrades instead of invalidating the plan that carries it: rejecting
the plan would discard the classifier's authorization decisions over
presentation metadata. Drop anything the current message cannot key, and
drop repeats — the client rejects a duplicated ID and falls back toView on GitHub (pinned to a1af029e6e)
Solutions
- Regenerate the request — transient model glitches usually clear on retry; consider a stronger model if it recurs
- Ensure any middleware that clones or retries tool calls assigns a fresh unique `id` to the copy
- Fix test fixtures by giving each constructed call a distinct id (e.g. `call_1`, `call_2`)
- If a provider integration systematically duplicates ids, upgrade or report it against the integration
Example fix
// before
[{"id": "call_1", "name": "read", "args": {"p": "a"}},
{"id": "call_1", "name": "read", "args": {"p": "b"}}]
// after
[{"id": "call_1", "name": "read", "args": {"p": "a"}},
{"id": "call_2", "name": "read", "args": {"p": "b"}}] Defensive patterns
Strategy: validation
Validate before calling
from collections.abc import Sequence
def ids_are_unique(calls: Sequence[dict]) -> bool:
ids = [c.get("id") for c in calls]
return len(ids) == len(set(ids)) Type guard
def has_unique_ids(calls: Sequence[dict]) -> bool:
return all(isinstance(c.get("id"), str) for c in calls) and len({c["id"] for c in calls}) == len(calls) Try / catch
try:
result = agent.invoke(input, config)
except ValueError as exc:
if "duplicate tool-call IDs" in str(exc):
retry_request_or_fix_synthesizing_middleware()
else:
raise Prevention
- When cloning/retrying a tool call in middleware, mint a fresh unique id
- Give every constructed call a distinct id in test fixtures
- Watch for provider/streaming bugs that duplicate ids; upgrade the integration
- Prefer models known to handle parallel tool calls correctly
When it happens
Trigger: A model response (or synthesized message) includes `tool_calls` where duplicate `id` values appear — e.g. a buggy model echoing the same id for parallel calls, a provider streaming bug, or test harness code duplicating a call dict.
Common situations: Faulty or quantized local models that emit parallel calls with identical ids; provider/proxy bugs collapsing parallel tool-call ids during streaming; middleware that clones a tool call (e.g. to retry) without minting a new id; hand-built test fixtures with copy-pasted call dicts.
Related errors
- trusted thread, turn, and tool-call identity are required
- Auto mode requires every proposed tool call to have an ID
- tool_call_id must not be empty
- deny decisions require a reason
- Human decision count does not match Manual pending calls
AI-assisted analysis of langchain-ai/deepagents@a1af029e6e (2026-08-29).
Data as JSON: /api/errors/73302e1998d7bad7.
Report an issue: GitHub.