HKUDS/Vibe-Trading · error · ValueError

Path {file_path!r} escapes run_dir {run_dir!r} and is not in

Error message

Path {file_path!r} escapes run_dir {run_dir!r} and is not in allowed {purpose} roots.

What it means

resolve_safe_path first tries containment under run_dir; if that fails it falls back to checking the resolved candidate against each allowed root for the given purpose. If no root contains it, this error listing run_dir and purpose is raised.

Source

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

        try:
            run_root = safe_run_dir(run_dir)
        except ValueError as exc:
            # If safe_run_dir fails, check if the path is in allowed_roots first
            candidate = Path(file_path).expanduser().resolve()
            for root in allowed_roots:
                if candidate.is_relative_to(root):
                    return candidate
            raise exc

        try:
            return safe_path(file_path, run_root)
        except ValueError as exc:
            # Fallback to allowed roots if safe_path containment fails
            candidate = Path(file_path).expanduser().resolve()
            for root in allowed_roots:
                if candidate.is_relative_to(root):
                    return candidate
            raise ValueError(
                f"Path {file_path!r} escapes run_dir {run_dir!r} and is not in allowed {purpose} roots."
            ) from exc

    # If no run_dir, path must resolve inside one of the allowed roots
    candidate = Path(file_path).expanduser().resolve()
    for root in allowed_roots:
        if candidate.is_relative_to(root):
            return candidate

    raise ValueError(
        f"run_dir is required to write/edit {file_path!r}, or the path must resolve inside allowed {purpose} roots."
    )


def _allowed_run_roots() -> list[Path]:
    """Return all roots allowed for run_dir-based tools."""
    raw = get_env_config().api.vibe_trading_allowed_run_roots
    configured: list[Path] = []

View on GitHub (pinned to 80ffdda44c)

Solutions

  1. Write inside run_dir (preferred for outputs)
  2. Add the target directory via the allowed-roots env var for the correct purpose
  3. Check that the env var is actually exported in the agent process, not just your shell

Example fix

# before
resolve_safe_path("/tmp/out.csv", run_dir, purpose="write")
# after
resolve_safe_path(str(run_dir / "out.csv"), run_dir, purpose="write")
Defensive patterns

Strategy: validation

Validate before calling

cand = Path(file_path).expanduser().resolve()
inside_run = run_dir is not None and cand.is_relative_to(Path(run_dir).resolve())
inside_roots = any(cand.is_relative_to(r) for r in allowed_roots)
assert inside_run or inside_roots

Type guard

def is_resolvable(p: str, run_dir: Path | None, roots: list[Path]) -> bool:
    c = Path(p).expanduser().resolve()
    return (run_dir is not None and c.is_relative_to(run_dir)) or any(c.is_relative_to(r) for r in roots)

Try / catch

try:
    target = resolve_safe_path(file_path, run_dir, purpose=purpose)
except ValueError as e:
    if "escapes run_dir" in str(e):
        target = run_dir / Path(file_path).name  # redirect into run_dir

Prevention

When it happens

Trigger: Passing a file_path that resolves neither under run_dir nor inside any allowed read/write root, e.g. /tmp/out.csv when /tmp is not allowlisted.

Common situations: Writing results to arbitrary temp/output directories, mismatched purpose (read roots vs write roots), or env var not set in the process that runs the tool.

Related errors


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