langchain-ai/deepagents · error · PluginManifestError
Could not read plugin manifest {manifest_path}: {exc}
Error message
Could not read plugin manifest {manifest_path}: {exc} What it means
`load_manifest` reads the manifest with `Path.read_text`; an `OSError` (missing permissions, I/O error, etc. — existence is checked earlier via `_find_manifest_path`) is wrapped as `PluginManifestError` with this message so all manifest failures surface as one exception type.
Source
Thrown at libs/code/deepagents_code/plugins/manifest.py:281
fallback_name: Name to use only when deriving a manifest-less plugin.
Returns:
`(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
View on GitHub (pinned to a1af029e6e)
Solutions
- Check permissions on the manifest file shown in the error and make it readable (`chmod u+r`).
- Verify the file still exists; reinstall the plugin to restore it.
- Avoid running installs as root so cache files don't become root-owned.
- Retry if the failure was transient (network filesystem).
Example fix
// before $ ls -l plugin.json # -rw------- root root // after $ sudo chown $(whoami) plugin.json && chmod u+rw plugin.json
Defensive patterns
Strategy: validation
Validate before calling
from pathlib import Path
p = Path("plugin.json")
if not p.is_file() or not p.stat().st_mode & 0o444:
raise SystemExit("manifest missing or unreadable") Try / catch
try:
manifest, _, _ = load_manifest(root)
except PluginManifestError as exc:
if "Could not read plugin manifest" in str(exc):
print(f"check permissions/restore file: {exc}")
else:
raise Prevention
- Keep cache files owned by the same user running the tool; avoid mixing sudo and normal runs.
- Don't delete plugin directories while installs/updates run.
- Verify readability of packaged manifests before shipping them.
- On network filesystems, expect transient read failures and retry.
When it happens
Trigger: `load_manifest` is called on a plugin root whose manifest file exists at discovery time but cannot be read: permission denied, file deleted between discovery and read, disk I/O error, or path is a broken special file.
Common situations: Manifest file made read-only or owned by another user (e.g. after `sudo` installs); a race where a concurrent update deletes the file; NFS/network mount hiccup; antivirus or backup tool locking the file on Windows.
Related errors
- debug log directory is not owned by the current user: {path}
- Cannot determine whether {str(left)!r} is {str(right)!r}: {e
- Invalid DEEPAGENTS_HOME {str(root)!r}: exists but cannot be
- Failed to read credential file {path}: {exc}. Check the file
- Failed to write credential file {auth_path()}: {exc}. Check
AI-assisted analysis of langchain-ai/deepagents@a1af029e6e (2026-08-29).
Data as JSON: /api/errors/8cce64f2433f47b7.
Report an issue: GitHub.