langchain-ai/deepagents · error · ValueError
Repository root must be an absolute contained path: {root!r}
Error message
Repository root must be an absolute contained path: {root!r} What it means
`RepositoryBounds.__init__` raises this `ValueError` when the `root` argument passed to it is not a safe absolute path. The root bounds all read-only repository inspection tools (ls, read_file, glob, grep), so it must be absolute (`startswith("/")`), must not contain `..` components, and must not contain `~`. Anything else could let path traversal escape the bounded sandbox, so construction fails fast.
Source
Thrown at libs/code/deepagents_code/_repository_bounds.py:83
class RepositoryBounds:
"""Path-safety and size limits for read-only repository inspection tools."""
def __init__(self, backend: BackendProtocol, *, root: str = "/") -> None:
"""Initialize repository bounds rooted at an absolute backend path.
Args:
backend: Server-side repository backend used by filesystem tools.
root: Absolute backend path that bounds repository reads.
Raises:
ValueError: If `root` is not a safe absolute path.
"""
normalized = root.replace("\\", "/")
path = PurePosixPath(normalized)
if not normalized.startswith("/") or ".." in path.parts or "~" in root:
msg = f"Repository root must be an absolute contained path: {root!r}"
raise ValueError(msg)
self._backend = backend
self._root = str(path)
self._sandbox = backend if isinstance(backend, SandboxBackendProtocol) else None
self._filesystem = (
backend
if self._sandbox is None and isinstance(backend, FilesystemBackend)
else None
)
self._filesystem_root: Path | None = None
if self._filesystem is not None:
try:
self._filesystem_root = self._resolve_filesystem_path(self._root)
except _BACKEND_ERRORS:
logger.warning(
"Could not resolve the local repository root; local repository "
"paths will be unavailable",
exc_info=True,
)View on GitHub (pinned to a1af029e6e)
Solutions
- Pass an absolute POSIX-style root: `RepositoryBounds(backend, root="/abs/path/to/repo")`.
- Resolve relative inputs first: `root = str(Path(user_root).expanduser().resolve())` before constructing.
- Remove or collapse `..` components with `Path.resolve()` or `os.path.normpath` plus absolutization.
- Convert Windows paths (drive letters, backslashes) to absolute POSIX paths appropriate for the backend environment.
Example fix
// before
bounds = RepositoryBounds(backend, root="~/project")
// after
from pathlib import Path
bounds = RepositoryBounds(backend, root=str(Path("~/project").expanduser().resolve())) Defensive patterns
Strategy: validation
Validate before calling
from pathlib import PurePosixPath
def safe_repository_root(root: str) -> bool:
normalized = root.replace("\\", "/")
path = PurePosixPath(normalized)
return (
normalized.startswith("/")
and ".." not in path.parts
and "~" not in root
) Type guard
def is_absolute_contained(path: str) -> bool:
p = PurePosixPath(path.replace("\\", "/"))
return path.startswith("/") and ".." not in p.parts and "~" not in path Try / catch
try:
bounds = RepositoryBounds(backend, root=resolved_root)
except ValueError as exc:
raise ConfigError(f"repository root rejected: {exc}") from exc Prevention
- Normalize with Path(...).expanduser().resolve() before passing any root.
- Never build roots by raw string concatenation; use pathlib joins.
- Convert Windows paths to the backend's expected absolute form first.
- Treat '~'-containing roots as user input needing expansion, never pass through.
When it happens
Trigger: Calling `RepositoryBounds(backend, root="repo")`, `root="~/repo"`, `root="/a/../b"`, or `root="C:\\repo"` (backslashes are normalized but the drive is not a leading `/`). Also triggered when a computed root from user config or CLI output is passed through unvalidated.
Common situations: Passing a Windows-style path on a POSIX-normalizing API; building the root by string concatenation without `os.path.abspath`; forwarding a user-supplied workspace path that contains `..` or `~`; using a relative default in a config file consumed by a server component that constructs `RepositoryBounds`.
Related errors
- Cannot determine whether {str(left)!r} is {str(right)!r}: {e
- Invalid DEEPAGENTS_HOME {configured!r}: use an absolute path
- allow_fs_tools must be None or a non-empty list
- SHELL_ALLOW_ALL should not be used with ShellAllowListMiddle
- interpreter_ptc='all' exposes every host tool to PTC calls t
AI-assisted analysis of langchain-ai/deepagents@a1af029e6e (2026-08-29).
Data as JSON: /api/errors/f2cb226391a24cc5.
Report an issue: GitHub.