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

  1. Pass an absolute POSIX-style root: `RepositoryBounds(backend, root="/abs/path/to/repo")`.
  2. Resolve relative inputs first: `root = str(Path(user_root).expanduser().resolve())` before constructing.
  3. Remove or collapse `..` components with `Path.resolve()` or `os.path.normpath` plus absolutization.
  4. 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

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


AI-assisted analysis of langchain-ai/deepagents@a1af029e6e (2026-08-29). Data as JSON: /api/errors/f2cb226391a24cc5. Report an issue: GitHub.