{"record":{"id":"8e49d390f74d4c7d","repo":"langchain-ai/deepagents","slug":"source-display-path-path-malformed-tools-j-8e49d3","errorCode":null,"errorMessage":"{source}: {_display_path(path)}: malformed tools.json: expected object","messagePattern":"(.+?): (.+?): malformed tools\\.json: expected object","errorType":"error_code","errorClass":"FleetImportError","httpStatus":null,"severity":"error","filePath":"libs/talon/deepagents_talon/fleet_import.py","lineNumber":361,"sourceCode":"        for child in sorted(agents.iterdir(), key=lambda item: item.name):\n            path = child / \"tools.json\"\n            if path.is_file():\n                paths.append((path, child.name))\n    return paths\n\n\ndef _load_tool_requests(path: Path, scope: str, source: Path) -> list[_ToolRequest]:\n    try:\n        data = json.loads(path.read_text(encoding=\"utf-8\"))\n    except json.JSONDecodeError as exc:\n        msg = f\"{source}: {_display_path(path)}: malformed tools.json: {exc.msg}\"\n        raise FleetImportError(msg) from exc\n    except OSError as exc:\n        msg = f\"{source}: {_display_path(path)}: {exc}\"\n        raise FleetImportError(msg) from exc\n    if not isinstance(data, dict):\n        msg = f\"{source}: {_display_path(path)}: malformed tools.json: expected object\"\n        raise FleetImportError(msg)\n\n    raw_tools = data.get(\"tools\")\n    if not isinstance(raw_tools, list):\n        msg = f\"{source}: {_display_path(path)}: malformed tools.json: expected tools list\"\n        raise FleetImportError(msg)\n    interrupt_config = data.get(\"interrupt_config\")\n    interrupts = interrupt_config if isinstance(interrupt_config, dict) else {}\n\n    requests: list[_ToolRequest] = []\n    for index, item in enumerate(raw_tools):\n        if not isinstance(item, dict):\n            msg = f\"{source}: {_display_path(path)}: tools[{index}] must be an object\"\n            raise FleetImportError(msg)\n        tool = cast(\"Mapping[str, object]\", item)\n        name = _required_str(tool, \"name\", path, index, source)\n        server_url = _sanitize_server_url(\n            _required_str(tool, \"mcp_server_url\", path, index, source)\n        )","sourceCodeStart":343,"sourceCodeEnd":379,"githubUrl":"https://github.com/langchain-ai/deepagents/blob/a1af029e6e73cb17c36bff823d227747b28e91e1/libs/talon/deepagents_talon/fleet_import.py#L343-L379","documentation":"The `tools.json` parsed as valid JSON but its top level is not a JSON object (e.g. an array, string, or number). The importer requires `dict` so it can read `tools` and `interrupt_config` keys, and aborts with this message otherwise.","triggerScenarios":"`import_fleet_zip` → `_load_tool_requests` finds `json.loads(...) != dict`, e.g. a tools.json containing `[...]` or `\"...\"` at top level.","commonSituations":"Export tooling writing a bare list of tools instead of the expected `{\"tools\": [...]}` wrapper; hand-edits that replaced the object with an array; wrong file exported (config.json renamed tools.json).","solutions":["Wrap the content: change top-level `[...]` to `{\"tools\": [...]}`","Add the required keys: `{\"tools\": [{\"name\": ..., \"mcp_server_url\": ..., \"mcp_server_name\": ...}]}`","Diff against a known-good tools.json from a working Fleet export to confirm the schema"],"exampleFix":"// before\n[{\"name\": \"search\", \"mcp_server_url\": \"https://mcp.example.com\", \"mcp_server_name\": \"web\"}]\n// after\n{\"tools\": [{\"name\": \"search\", \"mcp_server_url\": \"https://mcp.example.com\", \"mcp_server_name\": \"web\"}]}","handlingStrategy":"type-guard","validationCode":"import json\nfrom typing import Any\n\ndef validate_tools_schema(path):\n    data: Any = json.loads(open(path, encoding=\"utf-8\").read())\n    if not isinstance(data, dict) or not isinstance(data.get(\"tools\"), list):\n        raise ValueError(f\"{path}: must be an object with a 'tools' list\")","typeGuard":"from typing import Any\n\ndef is_tools_config(data: Any) -> bool:\n    return isinstance(data, dict) and isinstance(data.get(\"tools\"), list)","tryCatchPattern":"try:\n    import_fleet_zip(zip_path, target_dir=target)\nexcept FleetImportError as exc:\n    if \"malformed tools.json: expected object\" in str(exc):\n        print('Wrap content as {\"tools\": [...]}')\n    raise","preventionTips":["Always emit tools.json as an object with a `tools` key","Validate schema (dict + tools list) in your export pipeline","Keep a canonical example tools.json and diff against it"],"tags":["json","schema-validation","config","zip"],"backgroundTag":"schema-validation-failed","analyzedSha":"a1af029e6e73cb17c36bff823d227747b28e91e1","analyzedAt":"2026-08-29T11:43:24.718Z","schemaVersion":2},"datasetVersion":"2026-08-29T12:17:43.993Z"}