BerriAI/litellm · error · HTTPException
git-subdir source must include 'url' field (e.g., 'https://g
Error message
git-subdir source must include 'url' field (e.g., 'https://github.com/org/repo.git')
What it means
400 thrown by _validate_plugin_source() for a git-subdir plugin source that lacks a truthy "url" value. git-subdir sources point at a subdirectory of a git repository, so LiteLLM requires both the repository url and the relative path; this error fires on the missing/falsy url check (note it uses `if not source.get("url")`, so an empty string also triggers it).
Source
Thrown at litellm/proxy/anthropic_endpoints/claude_code_endpoints/claude_code_marketplace.py:183
def _validate_plugin_source(source: Mapping[str, str]) -> None:
"""Validate plugin source format, raising HTTPException on invalid input."""
source_type: Final = source.get("source")
if source_type == "github":
if "repo" not in source:
raise HTTPException(
status_code=400,
detail={"error": "GitHub source must include 'repo' field (e.g., 'org/repo')"},
)
elif source_type == "url":
if "url" not in source:
raise HTTPException(
status_code=400,
detail={"error": "URL source must include 'url' field (e.g., 'https://github.com/org/repo.git')"},
)
elif source_type == "git-subdir":
if not source.get("url"):
raise HTTPException(
status_code=400,
detail={
"error": "git-subdir source must include 'url' field (e.g., 'https://github.com/org/repo.git')"
},
)
if not source.get("path"):
raise HTTPException(
status_code=400,
detail={"error": "git-subdir source must include 'path' field (e.g., 'plugins/plugin-name')"},
)
if not _VALID_GIT_SUBDIR_PATH_RE.match(source["path"]):
raise HTTPException(
status_code=400,
detail={
"error": "git-subdir 'path' must be a relative path of the form 'segment/segment' (alphanumeric, dots, hyphens, underscores only)"
},
)
else:View on GitHub (pinned to 77b7c6c40c)
Solutions
- Include a non-empty repository url alongside the path: "source": {"source": "git-subdir", "url": "https://github.com/org/monorepo.git", "path": "plugins/my-plugin"}.
- Check that the url value is not an empty string — unlike the github/url checks, this branch rejects falsy values, not just missing keys.
- Verify the 'path' field is also present and matches the segment/segment allowlist, otherwise you will get the follow-up path validation error.
Example fix
# before
{"source": {"source": "git-subdir", "path": "plugins/my-plugin"}}
# after
{"source": {"source": "git-subdir", "url": "https://github.com/org/monorepo.git", "path": "plugins/my-plugin"}} Defensive patterns
Strategy: validation
Validate before calling
source = payload["source"]
if source.get("source") == "git-subdir":
if not source.get("url"):
raise ValueError("git-subdir source requires a non-empty 'url'")
if not source.get("path"):
raise ValueError("git-subdir source requires 'path'") Type guard
type GitSubdirSource = { source: 'git-subdir'; url: string; path: string };
function isGitSubdirSource(s: unknown): s is GitSubdirSource {
const o = s as Record<string, unknown>;
return (
!!o && o.source === 'git-subdir' &&
typeof o.url === 'string' && o.url.length > 0 &&
typeof o.path === 'string' && o.path.length > 0
);
} Prevention
- Treat git-subdir as a 3-field contract (source/url/path) and assert all three client-side.
- Reject empty-string values, not just missing keys — the server truthiness-checks url for this type.
When it happens
Trigger: POST /claude-code/plugins or PUT /claude-code/plugins/{name} with {"source": {"source": "git-subdir", "path": "plugins/my-plugin"}} — url absent — or with "url": "" (empty string), which fails the truthiness check.
Common situations: Splitting a monorepo plugin into git-subdir form and forgetting the repo URL; templating code that renders an empty url when the env/config variable is unset; assuming the path alone identifies the plugin.
Related errors
- GitHub source must include 'repo' field (e.g., 'org/repo')
- URL source must include 'url' field (e.g., 'https://github.c
- git-subdir source must include 'path' field (e.g., 'plugins/
- source.source must be 'github', 'url', or 'git-subdir'
- Plugin name must be kebab-case (lowercase letters, numbers,
AI-assisted analysis of BerriAI/litellm@77b7c6c40c (2026-08-18).
Data as JSON: /api/errors/28e3b2276d3e3268.
Report an issue: GitHub.