langchain-ai/deepagents · error · FleetImportError

{source}: {_display_path(path)}: tools[{index}] must be an o

Error message

{source}: {_display_path(path)}: tools[{index}] must be an object

What it means

FleetImportError raised when an element of the tools list in tools.json is not a JSON object. Each entry of the 'tools' array must be a mapping of tool fields (name, mcp_server_url, mcp_server_name).

Source

Thrown at libs/talon/deepagents_talon/fleet_import.py:374

    except OSError as exc:
        msg = f"{source}: {_display_path(path)}: {exc}"
        raise FleetImportError(msg) from exc
    if not isinstance(data, dict):
        msg = f"{source}: {_display_path(path)}: malformed tools.json: expected object"
        raise FleetImportError(msg)

    raw_tools = data.get("tools")
    if not isinstance(raw_tools, list):
        msg = f"{source}: {_display_path(path)}: malformed tools.json: expected tools list"
        raise FleetImportError(msg)
    interrupt_config = data.get("interrupt_config")
    interrupts = interrupt_config if isinstance(interrupt_config, dict) else {}

    requests: list[_ToolRequest] = []
    for index, item in enumerate(raw_tools):
        if not isinstance(item, dict):
            msg = f"{source}: {_display_path(path)}: tools[{index}] must be an object"
            raise FleetImportError(msg)
        tool = cast("Mapping[str, object]", item)
        name = _required_str(tool, "name", path, index, source)
        server_url = _sanitize_server_url(
            _required_str(tool, "mcp_server_url", path, index, source)
        )
        server_name = _required_str(tool, "mcp_server_name", path, index, source)
        requests.append(
            _ToolRequest(
                name=name,
                server_url=server_url,
                server_name=server_name,
                scope=scope,
                interrupt=_tool_interrupt_enabled(tool, interrupts, name, server_url, server_name),
            )
        )
    return requests

View on GitHub (pinned to a1af029e6e)

Solutions

  1. Fix the array element at the reported index so it is a JSON object with name, mcp_server_url, and mcp_server_name fields
  2. Re-export the fleet tools.json from source if it was generated
  3. Lint the file (e.g. jq '.tools | map(type)' tools.json) to find non-object entries

Example fix

// before
{"tools": ["my-tool"]}
// after
{"tools": [{"name": "my-tool", "mcp_server_url": "https://example.com", "mcp_server_name": "example"}]}
Defensive patterns

Strategy: validation

Validate before calling

data = json.loads(path.read_text())
bad = [i for i, t in enumerate(data.get("tools", [])) if not isinstance(t, dict)]
if bad:
    raise ValueError(f"non-object tool entries at indexes {bad}")

Type guard

def is_tool_entry(item: object) -> TypeGuard[dict[str, object]]:
    return isinstance(item, dict)

Try / catch

try:
    summaries = _mcp_summaries(...)
except FleetImportError as exc:
    logger.error("Bad tool entry in tools.json: %s", exc)
    raise

Prevention

When it happens

Trigger: A tools.json entry like "tools": ["name-only"] or [123] or [null]; iterating raw_tools with enumerate hits a non-dict item at the reported index.

Common situations: Hand-editing the list and dropping braces around an entry; JSON minifiers or scripts emitting scalars; copy-paste losing the object structure of one tool.

Understand the failure class

Background: Schema validation failed / invalid input schema: payload rejected because its shape doesn't match the expected schema — this error's family across 28 libraries.

Related errors


AI-assisted analysis of langchain-ai/deepagents@a1af029e6e (2026-08-29). Data as JSON: /api/errors/1a0d92093069fe6c. Report an issue: GitHub.