modelcontextprotocol/servers · error · BadName
Invalid contains value: '{contains}' - cannot start with '-'
Error message
Invalid contains value: '{contains}' - cannot start with '-' What it means
git_branch (server.py:273-305) raises git.exc.BadName when the 'contains' argument starts with '-'. This is defense-in-depth against flag injection: the value is later passed verbatim to repo.git.branch('--contains', contains), and a leading dash would make GitPython parse it as a git flag.
Source
Thrown at src/git/src/mcp_server_git/server.py:276
try:
resolved_repo = repo_path.resolve()
resolved_allowed = allowed_repository.resolve()
except (OSError, RuntimeError):
raise ValueError(f"Invalid path: {repo_path}")
# Check if repo_path is the same as or a subdirectory of allowed_repository
try:
resolved_repo.relative_to(resolved_allowed)
except ValueError:
raise ValueError(
f"Repository path '{repo_path}' is outside the allowed repository '{allowed_repository}'"
)
def git_branch(repo: git.Repo, branch_type: str, contains: str | None = None, not_contains: str | None = None) -> str:
# Defense in depth: reject values starting with '-' to prevent flag injection
if contains and contains.startswith("-"):
raise BadName(f"Invalid contains value: '{contains}' - cannot start with '-'")
if not_contains and not_contains.startswith("-"):
raise BadName(f"Invalid not_contains value: '{not_contains}' - cannot start with '-'")
match contains:
case None:
contains_sha = (None,)
case _:
contains_sha = ("--contains", contains)
match not_contains:
case None:
not_contains_sha = (None,)
case _:
not_contains_sha = ("--no-contains", not_contains)
match branch_type:
case 'local':
b_type = NoneView on GitHub (pinned to 76d64c822f)
Solutions
- Pass the bare ref or commit (e.g. 'main', 'abc123') as 'contains', never the '--contains' prefix.
- Strip a leading '--contains=' from user input before forwarding it.
- Validate client-side that the value does not start with '-' and looks like a ref.
- Reuse the same ref-sanitization helper you use for branch_name/revision/not_contains.
Example fix
// before
// arguments.get("contains") -> "--contains main" -> BadName
// after
// arguments.get("contains") -> "main" Defensive patterns
Strategy: validation
Validate before calling
def clean_ref_arg(v: str | None) -> str | None:
if v is None:
return None
v = v.strip()
if v.startswith("--contains="):
v = v[len("--contains="):]
if v.startswith("-"):
raise ValueError(f"ref argument must not start with '-': {v!r}")
if not v:
return None
return v
contains = clean_ref_arg(arguments.get("contains")) Type guard
def is_safe_ref_arg(v: object) -> bool:
return v is None or (isinstance(v, str) and not v.startswith("-") and v.strip() != "") Try / catch
from git.exc import BadName
try:
result = git_branch(repo, branch_type, contains, not_contains)
except BadName as e:
# reject the offending contains/not_contains value back to the user
log.warning("rejected ref arg: %s", e) Prevention
- Never prefix a ref argument with '--'; pass the bare ref/commit only.
- Strip a leading '--contains=' if you accept pasted shell input.
- Reuse one ref-sanitizer across contains, not_contains, branch_name, revision, target.
When it happens
Trigger: Calling the branch tool with a 'contains' value like '--all', '-v', '--contains=main', or any string beginning with '-'. Most often an LLM or user pasting the literal '--contains X' from a shell command instead of just the ref.
Common situations: Copy-pasting 'git branch --contains main' and passing '--contains main' as the value. Hallucinated flag prefixes from a model. Cross-contamination from the not_contains/--no-contains sibling argument.
Related errors
- Invalid target: '{target}' - cannot start with '-'
- Invalid start_timestamp: '{start_timestamp}' - cannot start
- Invalid end_timestamp: '{end_timestamp}' - cannot start with
- Invalid branch name: '{branch_name}' - cannot start with '-'
- Invalid base branch: '{base_branch}' - cannot start with '-'
AI-assisted analysis of modelcontextprotocol/servers@76d64c822f (2026-08-12).
Data as JSON: /api/errors/afc0f8ccbd1afc91.
Report an issue: GitHub.