langchain-ai/deepagents · error · MarketplaceError
GitHub marketplace URLs must contain exactly owner/repo
Error message
GitHub marketplace URLs must contain exactly owner/repo
What it means
For `https://github.com/...` URLs that are not `.git`-suffixed, the parser splits the path and expects exactly two segments (`owner/repo`) to convert the URL into a GitHub repository source (marketplace.py:180-190). If the path has more than two segments — e.g. a deep link into a subdirectory, a blob/tree URL, or an issues page — the parser refuses rather than guessing, since a marketplace must map to a whole repository.
Source
Thrown at libs/code/deepagents_code/plugins/marketplace.py:190
except ValueError as exc:
msg = "Invalid marketplace URL"
raise MarketplaceError(msg) from exc
path = parsed.path
if path.endswith(".git") or "/_git/" in path:
return RepositoryMarketplaceSource(
source_type="git", value=url, ref=ref or None
)
if parsed.hostname in {"github.com", "www.github.com"}:
parts = [part for part in path.split("/") if part]
if len(parts) == _GITHUB_REPO_PART_COUNT:
repo_path = "/".join(parts)
git_url = urlunparse(parsed._replace(path=f"/{repo_path}.git"))
return RepositoryMarketplaceSource(
source_type="git", value=git_url, ref=ref or None
)
if len(parts) > _GITHUB_REPO_PART_COUNT:
msg = "GitHub marketplace URLs must contain exactly owner/repo"
raise MarketplaceError(msg)
return UrlMarketplaceSource(source_type="url", value=url)
if value.startswith(("./", "../", "/", "~")):
return _marketplace_source_from_path(value)
# Bare relative paths such as `marketplace` (no ./ prefix) are accepted when
# they exist on disk, before GitHub-shorthand parsing.
candidate = Path(value).expanduser()
if candidate.exists():
return _marketplace_source_from_path(value)
repo, sep, ref = value.replace("#", "@", 1).partition("@")
if (
"/" in value
and ":" not in value
and not value.startswith("@")
and _GITHUB_REPO_RE.match(repo)
):View on GitHub (pinned to a1af029e6e)
Solutions
- Use the repository root URL `https://github.com/owner/repo` (exactly two path segments).
- Use the GitHub shorthand `owner/repo` instead of a full URL.
- If you truly want a file served over HTTPS, host the raw marketplace.json at a non-GitHub URL or use `https://raw.githubusercontent.com/...` only if it ends with `.json` outside the github.com host check (raw.githubusercontent.com is treated as a plain URL source).
Example fix
// before
add_marketplace_source("https://github.com/owner/repo/tree/main/.claude-plugin")
// after
add_marketplace_source("https://github.com/owner/repo") Defensive patterns
Strategy: validation
Validate before calling
from urllib.parse import urlparse
def validate_github_repo_url(raw: str) -> str:
url = raw.partition("#")[0]
parsed = urlparse(url)
if parsed.hostname in {"github.com", "www.github.com"}:
parts = [p for p in parsed.path.split("/") if p]
if len(parts) != 2:
raise ValueError(f"Use https://github.com/owner/repo, got: {url}")
return raw Type guard
from urllib.parse import urlparse
def is_github_repo_root(value: str) -> bool:
parsed = urlparse(value.partition("#")[0])
if parsed.hostname not in {"github.com", "www.github.com"}:
return False
return len([p for p in parsed.path.split("/") if p]) == 2 Try / catch
try:
source = parse_marketplace_source(raw)
except MarketplaceError as exc:
if "exactly owner/repo" in str(exc):
# Reduce a deep GitHub web URL to the repo root
parts = [p for p in urlparse(raw).path.split("/") if p]
raw = f"https://github.com/{parts[0]}/{parts[1]}"
source = parse_marketplace_source(raw)
else:
raise Prevention
- Use the `owner/repo` shorthand for GitHub marketplaces instead of full web URLs.
- Never paste GitHub tree/blob/issue URLs as marketplace sources.
- Document that a GitHub marketplace source must map to a whole repository.
When it happens
Trigger: `parse_marketplace_source('https://github.com/owner/repo/tree/main/marketplace.json')`, `'https://github.com/owner/repo/blob/main/.claude-plugin/marketplace.json'`, or any GitHub URL with 3+ path segments, via `add_marketplace_source` or `_plugin_repository_source`.
Common situations: Pasting a GitHub web UI URL (tree/blob view) instead of the repo root; linking to a marketplace.json file inside a repo rather than the repo itself; trailing deep paths from GitHub search results.
Related errors
- remote source must be an absolute HTTPS URL
- remote source must not contain credentials
- remote source must not contain a query string or fragment
- remote source has an invalid port
- remote_source must be a validated absolute HTTPS URL
AI-assisted analysis of langchain-ai/deepagents@a1af029e6e (2026-08-29).
Data as JSON: /api/errors/dc2c1461036e009a.
Report an issue: GitHub.