langchain-ai/deepagents · error · MarketplaceError
{unresolved_source_message(plugin_id, entry, rejections)}
Error message
{unresolved_source_message(plugin_id, entry, rejections)} What it means
install_plugin materializes the plugin's source from the marketplace into a local root; when materialize_plugin_source returns None it populates `rejections` explaining why candidate sources were rejected, and install_plugin raises MarketplaceError with unresolved_source_message summarizing them. It means no valid local copy of the plugin source could be produced from the marketplace entry.
Source
Thrown at libs/code/deepagents_code/plugins/discovery.py:226
writes `installed_plugins.json`, and enables the plugin.
Args:
plugin_id: Plugin id in `{name}@{marketplace}` form.
Returns:
Discovered plugin instance loaded from the cache path.
Raises:
MarketplaceError: If the marketplace/plugin cannot be resolved, the
source is unsupported, or the cached plugin fails to load.
"""
load_installed_plugins(strict=True)
load_enabled_plugin_ids(strict=True)
marketplace, entry = _resolve_marketplace_and_entry(plugin_id)
rejections: list[str] = []
source_root = materialize_plugin_source(marketplace, entry, rejections=rejections)
if source_root is None:
raise MarketplaceError(unresolved_source_message(plugin_id, entry, rejections))
try:
manifest, _manifest_path, manifest_warnings = load_manifest(
source_root, fallback_name=entry.name
)
except PluginManifestError as exc:
msg = f"Cannot install {plugin_id}: {exc}"
raise MarketplaceError(msg) from exc
for warning in manifest_warnings:
logger.debug("Plugin install warning for %s: %s", plugin_id, warning)
version = manifest.version if manifest is not None else None
cache_path = cache_and_register_plugin(
plugin_id,
source_root,
version=version,
validate=partial(View on GitHub (pinned to a1af029e6e)
Solutions
- Read the unresolved_source_message — the embedded rejections name each rejected source and reason.
- Re-add or refresh the marketplace so its source location is intact and current.
- Remove forbidden symlinks (or point them inside the plugin) in the plugin source.
- Check the cache/install directories for permissions and disk space.
- If the source lives remotely, verify the fetch (URL reachable, credentials valid) then retry.
Example fix
// before (plugin dir contains a symlink escaping the plugin) src -> /usr/share/evil # rejected # after ln -s ./vendor src # symlink stays inside the plugin $ dcode plugin install widget@internal
Defensive patterns
Strategy: validation
Validate before calling
from pathlib import Path
def source_root_sane(root: Path) -> bool:
if not root.is_dir():
return False
for link in root.rglob("*"):
if link.is_symlink():
target = link.resolve()
if not target.is_relative_to(root.resolve()):
return False # symlink escapes plugin dir -> will be rejected
return True
assert source_root_sane(Path("plugins/widget")) Type guard
def symlink_safe(root: Path) -> bool:
root_resolved = root.resolve()
return all(
not p.is_symlink() or p.resolve().is_relative_to(root_resolved)
for p in root.rglob("*")
) Try / catch
try:
install_plugin("widget@internal")
except MarketplaceError as exc:
print("source unresolved:", exc) # rejections list explains each rejected candidate
# remediate: refresh marketplace, fix symlinks, check disk/permissions Prevention
- Keep all symlinks inside the plugin directory.
- Refresh/re-add marketplaces so install_location stays valid.
- Check disk space and write permissions on cache dirs.
- Verify remote sources are fetchable before installing.
- Inspect the rejections in the message — they name each cause.
When it happens
Trigger: materialize_plugin_source fails for all candidate sources — e.g. checkout/copy refused (symlink escaping the plugin directory, missing files), cache write failure, or the marketplace entry pointing at a nonexistent source path; the rejections list is embedded in the message.
Common situations: A plugin repo containing symlinks that point outside the plugin (deliberately rejected for safety); a marketplace install_location deleted or moved on disk; partial/corrupted marketplace checkout; network fetch failures during materialization.
Related errors
- debug log directory is not a real directory: {path}
- Failed to install {args.plugin_id}: {exc}
- Cannot install {plugin_id}: {exc}
- Path is neither a file nor a directory: {path}
- Error: Skill directory is a symlink. Refusing to delete for
AI-assisted analysis of langchain-ai/deepagents@a1af029e6e (2026-08-29).
Data as JSON: /api/errors/10fd8b5e6a184d4f.
Report an issue: GitHub.