CoplayDev/unity-mcp · error · ValueError
Command '{tool_name}' must specify parameters as an object/d
Error message
Command '{tool_name}' must specify parameters as an object/dict What it means
In batch_execute, each command's 'params' value must be either absent (defaults to {}), None (normalized to {}), or a dict. The check `not isinstance(params, dict)` after the None-normalization rejects lists, strings, numbers, and other non-mapping types. params carries the keyword arguments forwarded to the target Unity tool, so it must be a JSON object. The tool_name is included in the message for context.
Source
Thrown at Server/src/services/tools/batch_execute.py:116
)
normalized_commands: list[dict[str, Any]] = []
for index, command in enumerate(commands):
if not isinstance(command, dict):
raise ValueError(
f"Command at index {index} must be an object with 'tool' and 'params' keys")
tool_name = command.get("tool")
params = command.get("params", {})
if not tool_name or not isinstance(tool_name, str):
raise ValueError(
f"Command at index {index} is missing a valid 'tool' name")
if params is None:
params = {}
if not isinstance(params, dict):
raise ValueError(
f"Command '{tool_name}' must specify parameters as an object/dict")
if "unity_instance" in params:
raise ValueError(
f"Command '{tool_name}' at index {index} contains 'unity_instance'. "
"Per-command instance routing is not supported inside batch_execute. "
"Set unity_instance on the outer batch_execute call to route the entire batch."
)
normalized_commands.append({
"tool": tool_name,
"params": params,
})
payload: dict[str, Any] = {
"commands": normalized_commands,
}
View on GitHub (pinned to c21bf496bc)
Solutions
- Pass params as a JSON object (dict) of keyword arguments: {"tool": "manage_gameobject", "params": {"action": "create", "name": "Cube"}}.
- If the tool takes no parameters, omit params or set it to {}.
- Check the tool_name in the message to locate which command has the bad params.
Example fix
// before
commands=[{"tool": "manage_gameobject", "params": ["create", "Cube"]}]
// after
commands=[{"tool": "manage_gameobject", "params": {"action": "create", "name": "Cube"}}] Defensive patterns
Strategy: type-guard
Validate before calling
# Ensure params is a dict (or absent/None) for each command
for i, c in enumerate(commands):
params = c.get("params", {})
if params is None:
c["params"] = {}
elif not isinstance(params, dict):
raise ValueError(f"Command {i} ({c.get('tool')}) params must be a dict, got {type(params).__name__}") Type guard
def all_params_are_dicts(commands: list) -> bool:
for c in commands:
if not isinstance(c, dict):
continue
p = c.get("params", {})
if p is not None and not isinstance(p, dict):
return False
return True Prevention
- Pass params as a JSON object of keyword arguments, never as a list or string.
- Omit params or use {} for tools that take no arguments.
- Validate params types in your command builder before batching.
When it happens
Trigger: A command passes params as a list: {"tool": "x", "params": [1, 2]}; params is a JSON string; params is a number; a caller serializes params as a query string instead of an object.
Common situations: An LLM generates params as an array of positional args instead of a kwargs object; a caller confuses params with a list of values; a serialization bug where params is double-encoded as a string.
Related errors
- 'commands' must be a non-empty list of command specification
- Command at index {index} must be an object with 'tool' and '
- Command at index {index} is missing a valid 'tool' name
- batch_execute supports up to {max_commands} commands (config
- Command '{tool_name}' at index {index} contains 'unity_insta
AI-assisted analysis of CoplayDev/unity-mcp@c21bf496bc (2026-08-13).
Data as JSON: /api/errors/48df2e532743d942.
Report an issue: GitHub.