modelcontextprotocol/servers · error · ValueError
Invalid path: '{f}'
Error message
Invalid path: '{f}' What it means
In git_add(), each file path is resolved via (repo_root / f).resolve(); an OSError or RuntimeError (broken symlink, symlink loop, path with null bytes or illegal characters, permission error during resolution) is caught and rethrown as ValueError 'Invalid path: ...'. This is the resolve step, before the inside-repo check.
Source
Thrown at src/git/src/mcp_server_git/server.py:144
return repo.git.diff(f"--unified={context_lines}", target)
def git_commit(repo: git.Repo, message: str) -> str:
commit = repo.index.commit(message)
return f"Changes committed successfully with hash {commit.hexsha}"
def git_add(repo: git.Repo, files: list[str]) -> str:
if files == ["."]:
repo.git.add(".")
else:
# Defense in depth: validate each path resolves within the repository
# working tree to prevent path traversal (e.g. '../../etc/passwd' or an
# absolute path) from staging files outside repository boundaries.
repo_root = Path(repo.working_dir).resolve()
for f in files:
try:
resolved = (repo_root / f).resolve()
except (OSError, RuntimeError):
raise ValueError(f"Invalid path: '{f}'")
try:
resolved.relative_to(repo_root)
except ValueError:
raise ValueError(
f"Path '{f}' is outside the repository '{repo_root}'"
)
# Use '--' to prevent files starting with '-' from being interpreted as options
repo.git.add("--", *files)
return "Files staged successfully"
def git_reset(repo: git.Repo) -> str:
repo.index.reset()
return "All staged changes reset"
def git_log(repo: git.Repo, max_count: int = 10, start_timestamp: Optional[str] = None, end_timestamp: Optional[str] = None) -> list[str]:
if start_timestamp or end_timestamp:
# Defense in depth: reject timestamps starting with '-' to prevent flag injection
if start_timestamp and start_timestamp.startswith("-"):View on GitHub (pinned to 76d64c822f)
Solutions
- Verify the path exists and is not a broken symlink before staging.
- Remove or repair the offending symlink.
- Sanitize paths of null bytes and illegal characters before calling.
Example fix
# before
git_add(repo, files=['link-to-nowhere']) # dangling symlink -> ValueError
# after
def clean_add(repo, files):
root = Path(repo.working_dir).resolve()
ok = [f for f in files if (root / f).exists()]
return git_add(repo, ok) Defensive patterns
Strategy: validation
Validate before calling
from pathlib import Path
def resolvable(repo, f: str) -> bool:
try:
(Path(repo.working_dir).resolve() / f).resolve()
return True
except (OSError, RuntimeError):
return False Try / catch
try:
git_add(repo, files)
except ValueError as e:
if e.args[0].startswith('Invalid path:'):
# drop/repair the offending path and retry
raise Prevention
- Check paths exist and are not broken symlinks before staging.
- Sanitize input of null bytes and illegal characters.
- Operate only on paths returned by your directory listing.
When it happens
Trigger: A staged path is a dangling symlink; a symlink forms a loop; the path contains illegal characters or null bytes; resolve() hits a permissions error.
Common situations: Broken symlinks left in the working tree; OS-level path quirks; paths from untrusted input containing control characters.
Related errors
- Invalid path: {repo_path}
- Invalid target: '{target}' - cannot start with '-'
- Path '{f}' is outside the repository '{repo_root}'
- Invalid start_timestamp: '{start_timestamp}' - cannot start
- Invalid end_timestamp: '{end_timestamp}' - cannot start with
AI-assisted analysis of modelcontextprotocol/servers@76d64c822f (2026-08-12).
Data as JSON: /api/errors/615b0cf047aaffe0.
Report an issue: GitHub.