shareAI-lab/learn-claude-code · error · ValueError
Path escapes workspace: {p}
Error message
Path escapes workspace: {p} What it means
safe_path() resolves a user/model-supplied relative path against a base (default WORKDIR) and raises if the resolved path is not inside that base. It is the guardrail that keeps every file-oriented tool from touching anything outside the workspace, including '../' escapes and absolute paths that resolve elsewhere.
Source
Thrown at s13_agent_teams/code.py:612
"only; it is not a sandbox. Worktree removal stays with the host or "
"user. After spawning a teammate, end the current turn instead of "
"polling its status; the runtime will deliver team events and wake the "
"Lead. React to those events, and shut teammates down when "
"coordination is complete."
),
"workspace": f"Working directory: {WORKDIR}",
}
SYSTEM = "\n\n".join(PROMPT_SECTIONS.values())
# -- Base Tools --
def safe_path(p: str, cwd: Path | None = None) -> Path:
base = (cwd or WORKDIR).resolve()
path = (base / p).resolve()
if not path.is_relative_to(base):
raise ValueError(f"Path escapes workspace: {p}")
return path
def run_bash(command: str, cwd: Path | None = None) -> str:
try:
result = subprocess.run(
command,
shell=True,
cwd=cwd or WORKDIR,
capture_output=True,
text=True,
timeout=120,
)
output = (result.stdout + result.stderr).strip()
output = output[:50000] if output else "(no output)"
if result.returncode:
return f"Error: command exited with status {result.returncode}\n{output}"
return outputView on GitHub (pinned to 985456f4ad)
Solutions
- Pass paths relative to the workspace root and stay inside it.
- If a file legitimately lives outside, copy it into the workspace first.
- For nested agents, pass the agent's worktree as cwd so its relative paths resolve inside its own scope.
- Remove symlinks inside the workspace that point outside, or expect them to be rejected.
Example fix
// before
read_file(safe_path('../../shared/config.yaml')) // ValueError
// after
run_bash('cp /shared/config.yaml ./config.yaml')
read_file(safe_path('config.yaml')) Defensive patterns
Strategy: validation
Validate before calling
from pathlib import Path
def path_in_workspace(p: str, base: Path | None = None) -> bool:
base = (base or WORKDIR).resolve()
return (base / p).resolve().is_relative_to(base) Try / catch
try:
resolved = safe_path(user_path)
except ValueError as exc:
if 'escapes workspace' in str(exc):
return error_to_model(f'{user_path!r} is outside the workspace; use a relative path')
raise Prevention
- Always call file tools with paths relative to WORKDIR (or the agent's worktree cwd).
- Copy external files into the workspace instead of referencing absolute paths.
- For nested agents, pass their worktree as cwd so their relative paths resolve inside it.
When it happens
Trigger: safe_path('../outside.txt'), safe_path('/etc/passwd') (absolute path joined then resolved outside base), or a path whose intermediate symlink component points outside the workspace; also passing a path with cwd= pointing to a directory that doesn't contain the result.
Common situations: Model-generated file tool calls referencing parent directories or absolute paths; symlinks inside the repo pointing to dotfiles elsewhere; tests calling tools with repo-external fixtures.
Related errors
- Path escapes workspace: {p}
- Path escapes workspace: {p}
- Path escapes workspace: {p}
- Path escapes workspace: {p}
- Path escapes workspace: {p}
AI-assisted analysis of shareAI-lab/learn-claude-code@985456f4ad (2026-08-14).
Data as JSON: /api/errors/77687dcb198f4f81.
Report an issue: GitHub.