CoplayDev/unity-mcp · error · ValueError

Command at index {index} is missing a valid 'tool' name

Error message

Command at index {index} is missing a valid 'tool' name

What it means

In batch_execute's per-command loop, after confirming the command is a dict, the 'tool' key must be present and be a non-empty string. The check `not tool_name or not isinstance(tool_name, str)` catches missing key, None, empty string, and non-string types (e.g., a number). The index is included for locating the bad entry. This guards against dispatching a batch sub-command to a non-existent or unnameable tool.

Source

Thrown at Server/src/services/tools/batch_execute.py:110

            "'commands' must be a non-empty list of command specifications")

    max_commands = await _get_max_commands_from_editor_state(ctx)
    if len(commands) > max_commands:
        raise ValueError(
            f"batch_execute supports up to {max_commands} commands (configured in Unity); received {len(commands)}"
        )

    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,

View on GitHub (pinned to c21bf496bc)

Solutions

  1. Ensure every command dict has "tool": "<exact_tool_name>" with a non-empty string value.
  2. Check the index in the error message to find the offending entry.
  3. Verify the tool name is a registered MCP tool (e.g., 'manage_gameobject', 'manage_script').

Example fix

// before
commands=[{"name": "manage_gameobject", "params": {"action": "create"}}]
// after
commands=[{"tool": "manage_gameobject", "params": {"action": "create"}}]
Defensive patterns

Strategy: type-guard

Validate before calling

# Ensure every command has a valid non-empty string 'tool'
for i, c in enumerate(commands):
    tool = c.get("tool")
    if not isinstance(tool, str) or not tool.strip():
        raise ValueError(f"Command {i} has no valid 'tool' name")

Type guard

def has_valid_tool_names(commands: list) -> bool:
    return all(
        isinstance(c.get("tool"), str) and c.get("tool", "").strip() != ""
        for c in commands
        if isinstance(c, dict)
    )

Prevention

When it happens

Trigger: A command dict omits 'tool' entirely: {"params": {...}}; 'tool' is set to null or '' ; 'tool' is a number or list; a caller uses a wrong key like 'name' or 'command' instead of 'tool'.

Common situations: An LLM uses 'name' or 'command' as the key instead of 'tool'; a caller copies a tool schema fragment that lacks the tool field; a JSON key typo; a dynamically-built command where the tool name variable was None.

Related errors


AI-assisted analysis of CoplayDev/unity-mcp@c21bf496bc (2026-08-13). Data as JSON: /api/errors/ae0aa81b8960aa79. Report an issue: GitHub.