BerriAI/litellm · error · HTTPException
git-subdir 'path' must be a relative path of the form 'segme
Error message
git-subdir 'path' must be a relative path of the form 'segment/segment' (alphanumeric, dots, hyphens, underscores only)
What it means
400 thrown when a git-subdir source's "path" fails the allowlist regex ^[a-zA-Z0-9][a-zA-Z0-9._-]*(/[a-zA-Z0-9][a-zA-Z0-9._-]*)*$ — one or more '/'-separated segments, each starting alphanumeric and containing only alphanumerics, dots, hyphens, underscores. This is a security guard: it blocks path traversal ('..'), absolute paths, backslashes, and percent-encoded sequences before the path is ever used against a git checkout.
Source
Thrown at litellm/proxy/anthropic_endpoints/claude_code_endpoints/claude_code_marketplace.py:195
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:
raise HTTPException(
status_code=400,
detail={"error": "source.source must be 'github', 'url', or 'git-subdir'"},
)
def _build_plugin_manifest(name: str, spec: PluginSpec) -> Mapping[str, object]:
"""Build the stored manifest dict shared by plugin create and update."""
dumped: Final[Mapping[str, object]] = spec.model_dump(exclude_none=True)
return {"name": name, **{key: value for key, value in dumped.items() if value and key != "name"}}
View on GitHub (pinned to 77b7c6c40c)
Solutions
- Use a plain relative path of allowed segments, e.g. "plugins/my-plugin" or "packages/pkg.name".
- Remove any leading '/', '..', backslashes, or percent-encoding before sending; strip and re-join the path client-side if it comes from user input.
- If the real plugin directory starts with a dot or other disallowed character, rename the directory in the repo rather than fighting the allowlist.
Example fix
# before
{"source": {"source": "git-subdir", "url": "https://github.com/org/repo.git", "path": "../secrets"}}
# after
{"source": {"source": "git-subdir", "url": "https://github.com/org/repo.git", "path": "plugins/plugin-name"}} Defensive patterns
Strategy: validation
Validate before calling
import re
VALID = re.compile(r"^[a-zA-Z0-9][a-zA-Z0-9._-]*(/[a-zA-Z0-9][a-zA-Z0-9._-]*)*$")
path = source["path"]
path = path.replace("\\", "/")
if not VALID.match(path) or ".." in path.split("/"):
raise ValueError(f"git-subdir path {path!r} not allowed; use 'segment/segment' form")
source["path"] = path Type guard
const GIT_SUBDIR_PATH = /^[a-zA-Z0-9][a-zA-Z0-9._-]*(\/[a-zA-Z0-9][a-zA-Z0-9._-]*)*$/;
function isSafeSubdirPath(p: unknown): p is string {
return typeof p === 'string' && GIT_SUBDIR_PATH.test(p) && !p.split('/').includes('..');
} Prevention
- Mirror the server's segment allowlist client-side and normalize backslashes/URL-decoding before sending.
- Reject any path containing '..', leading '/', or percent signs as a hard error in your tooling.
- Keep plugin directories named with plain alphanumerics, dots, hyphens, underscores.
When it happens
Trigger: Registering a plugin with path values like "../other-plugin", "/plugins/my-plugin", "..\\plugins\\my-plugin", "%2e%2e/plugins", "plugins//my-plugin" (empty segment), or ".hidden/plugin" (segment starting with a dot) — all fail the regex and get this 400.
Common situations: Pointing the path outside the intended directory (traversal attempts or copy-pasted absolute paths from a local checkout); Windows-style backslash paths; URL-encoded paths passed through a client that pre-encodes; leading-dot directories like '.github'.
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 'url' field (e.g., 'https://g
- git-subdir source must include 'path' field (e.g., 'plugins/
- source.source must be 'github', 'url', or 'git-subdir'
AI-assisted analysis of BerriAI/litellm@77b7c6c40c (2026-08-18).
Data as JSON: /api/errors/cf54f928f00933a8.
Report an issue: GitHub.