langchain-ai/deepagents · error · PluginManifestError
Plugin manifest {manifest_path} must be a JSON object
Error message
Plugin manifest {manifest_path} must be a JSON object What it means
After successfully parsing the manifest JSON, `load_manifest` requires the decoded value to be a JSON object (dict). If the file parses but contains a list, string, number, or `null`, this `PluginManifestError` is raised — the manifest schema is object-shaped (`name`, `version`, component path fields).
Source
Thrown at libs/code/deepagents_code/plugins/manifest.py:284
`(manifest, manifest_path, warnings)`.
Raises:
PluginManifestError: If the manifest exists but is invalid.
"""
manifest_path = find_manifest_path(root)
if manifest_path is None:
return None, None, ()
try:
decoded = json.loads(manifest_path.read_text(encoding="utf-8"))
except json.JSONDecodeError as exc:
msg = f"Invalid JSON syntax in {manifest_path}: {exc}"
raise PluginManifestError(msg) from exc
except OSError as exc:
msg = f"Could not read plugin manifest {manifest_path}: {exc}"
raise PluginManifestError(msg) from exc
if not isinstance(decoded, dict):
msg = f"Plugin manifest {manifest_path} must be a JSON object"
raise PluginManifestError(msg)
raw = json_object(decoded)
warnings: list[str] = []
name = _validate_name(raw.get("name"), fallback=fallback_name)
component_paths: dict[str, tuple[Path, ...]] = {}
for field_name in _PATH_COMPONENT_FIELDS:
declaration = raw.get(field_name)
if declaration is None:
continue
if field_name in {"mcpServers", "hooks"} and isinstance(declaration, dict):
continue
paths = _resolve_component_paths(declaration, root, field_name, warnings)
if paths:
component_paths[field_name] = paths
version_value = raw.get("version")
version = version_value if isinstance(version_value, str) else None
display_name_value = raw.get("displayName")View on GitHub (pinned to a1af029e6e)
Solutions
- Reshape the manifest to a top-level JSON object with fields like `name`, `version`, and component paths.
- If it's a list of manifests, split into one object per plugin directory.
- Validate with `python -c "import json,sys; d=json.load(open('plugin.json')); assert isinstance(d, dict)"` before publishing.
Example fix
// before
[{"name": "x", "version": "1.0"}]
// after
{"name": "x", "version": "1.0"} Defensive patterns
Strategy: type-guard
Validate before calling
import json
from pathlib import Path
d = json.loads(Path("plugin.json").read_text(encoding="utf-8"))
assert isinstance(d, dict), "manifest must be a JSON object, not a list/string" Type guard
def is_manifest_object(decoded: object) -> bool:
return isinstance(decoded, dict) Try / catch
try:
manifest, _, _ = load_manifest(root)
except PluginManifestError as exc:
if "must be a JSON object" in str(exc):
print(f"reshape manifest to a top-level object: {exc}") Prevention
- A manifest is always a single JSON object — never an array of objects.
- If a generator emits lists, write one object per plugin directory.
- Type-check the parsed document before saving manifests in tooling.
When it happens
Trigger: `load_manifest` is called on a plugin root whose manifest file contains valid JSON that is not an object — e.g. a top-level array, a bare quoted string, or `null`.
Common situations: Author wrapped the manifest in an array `[ {...} ]`; file accidentally contains only a version string; a generator/export tool emitted a JSON list of manifests instead of one object.
Related errors
- Invalid JSON syntax in {manifest_path}: {exc}
- External event must be a JSON object
- External event kind must be one of {sorted(_VALID_KINDS)}; g
- Invalid plugin name: {name!r}
- Could not read plugin manifest {manifest_path}: {exc}
AI-assisted analysis of langchain-ai/deepagents@a1af029e6e (2026-08-29).
Data as JSON: /api/errors/becd909007e7911c.
Report an issue: GitHub.