HKUDS/Vibe-Trading · error · ValueError

Path {p!r} escapes the workspace root

Error message

Path {p!r} escapes the workspace root

What it means

safe_path expands the input, resolves it against the workspace base, and requires the resolved path to stay inside base via Path.relative_to. Anything that resolves outside (absolute path elsewhere, '..' traversal, symlink escaping) raises this error.

Source

Thrown at agent/src/tools/path_utils.py:73

        Absolute resolved path inside `workdir`.

    Raises:
        ValueError: If `p` uses a UNC share, or its resolved form escapes
            `workdir`. Callers surface this back to the LLM as a tool error.
    """
    _rejects_unc(p)
    base = Path(workdir).resolve()
    # Expand ~ so home-relative paths (e.g. ~/.vibe-trading/scripts/foo.py)
    # resolve correctly instead of being treated as literal directory names.
    expanded = Path(p).expanduser()
    if expanded.is_absolute():
        resolved = expanded.resolve()
    else:
        resolved = (base / p).resolve()
    try:
        resolved.relative_to(base)
    except ValueError as exc:
        raise ValueError(f"Path {p!r} escapes the workspace root") from exc
    return resolved


def _agent_root() -> Path:
    """Return the agent package root."""
    return Path(__file__).resolve().parents[2]


def _configured_file_roots() -> list[Path]:
    """Return file roots configured through the environment."""
    raw = get_env_config().api.vibe_trading_allowed_file_roots
    roots: list[Path] = []
    for item in raw.split(","):
        item = item.strip()
        if not item:
            continue
        _rejects_unc(item)
        roots.append(Path(item).expanduser().resolve())

View on GitHub (pinned to 80ffdda44c)

Solutions

  1. Use paths relative to the workspace root without '..' segments
  2. Place needed files inside workdir first
  3. If a file legitimately lives elsewhere, add its directory via the allowed-roots env var instead of bypassing

Example fix

# before
safe_path("../../etc/passwd", workdir)
# after
safe_path("data/input.csv", workdir)
Defensive patterns

Strategy: type-guard

Validate before calling

from pathlib import Path
cand = (workdir / file_path).resolve()
if workdir not in cand.parents and cand != workdir:
    raise ArgumentError(f"{file_path} escapes workspace")

Type guard

def stays_inside(p: str, base: Path) -> bool:
    try:
        (base / p).resolve().relative_to(base)
        return True
    except ValueError:
        return False

Try / catch

try:
    resolved = safe_path(file_path, workdir)
except ValueError as e:
    if "escapes the workspace root" in str(e):
        file_path = relocate_into(file_path, workdir)

Prevention

When it happens

Trigger: Passing '../..' style relative paths, absolute paths outside workdir, or a symlink inside workdir pointing outside that resolves beyond the root.

Common situations: Generated code using absolute temp paths, prompts referencing files outside the workspace, or symlinks created by build tooling.

Related errors


AI-assisted analysis of HKUDS/Vibe-Trading@80ffdda44c (2026-08-28). Data as JSON: /api/errors/41c80d037553244c. Report an issue: GitHub.