langchain-ai/langgraph · error · ValueError
Tools can provide a dict in Command.update only when using…
Error message
Tools can provide a dict in Command.update only when using dict with '{messages_key}' key as ToolNode input, got: {update} for tool '{name}' What it means
Shape check in _validate_tool_command: the tool returned a Command whose update is a dict, but ToolNode was invoked with a list-of-messages input. Dict updates (keyed by state key like 'messages') are only meaningful when the node input is a state dict; otherwise the keys cannot be mapped.
Solutions
- Return the update as a list of messages: `Command(update=[ToolMessage(...)])` when invoking ToolNode with a message list
- Or invoke ToolNode with a dict state ({"messages": [...]}) so dict updates are allowed
Defensive patterns
Strategy: validation
When it happens
Trigger: Thrown at libs/prebuilt/langgraph/prebuilt/tool_node.py:1520 when the library encounters an invalid state.
Common situations: See trigger scenarios.
AI-assisted analysis of langchain-ai/langgraph@38031739e5 (2026-08-26).
Data as JSON: /api/errors/e55055631b686951.
Report an issue: GitHub.
Appendix: source
Thrown at libs/prebuilt/langgraph/prebuilt/tool_node.py:1520
def _validate_tool_command(
self,
command: Command,
call: ToolCall,
input_type: Literal["list", "dict", "tool_calls"],
*,
require_terminator: bool = True,
) -> Command:
if isinstance(command.update, dict):
# input type is dict when ToolNode is invoked with a dict input
# (e.g. {"messages": [AIMessage(..., tool_calls=[...])]})
if input_type not in ("dict", "tool_calls"):
msg = (
"Tools can provide a dict in Command.update only when using dict "
f"with '{self._messages_key}' key as ToolNode input, "
f"got: {command.update} for tool '{call['name']}'"
)
raise ValueError(msg)
updated_command = deepcopy(command)
state_update = cast("dict[str, Any]", updated_command.update) or {}
messages_update = state_update.get(self._messages_key, [])
elif isinstance(command.update, list):
# Input type is list when ToolNode is invoked with a list input
# (e.g. [AIMessage(..., tool_calls=[...])])
if input_type != "list":
msg = (
"Tools can provide a list of messages in Command.update "
"only when using list of messages as ToolNode input, "
f"got: {command.update} for tool '{call['name']}'"
)
raise ValueError(msg)
updated_command = deepcopy(command)
messages_update = updated_command.update
else:View on GitHub (pinned to 38031739e5)