can1357/oh-my-pi · error · ValueError
Protocol paths are not supported by this helper: {path}
Error message
Protocol paths are not supported by this helper: {path} What it means
The eval Python prelude's _resolve_omp_path maps scheme-based paths (e.g. file:// or omp:// URIs) onto a host root directory supplied via the PI_EVAL_LOCAL_ROOTS env var (a JSON map of scheme -> root). If the URL's scheme has no entry in that map (or the env var is absent/malformed), it raises ValueError 'Protocol paths are not supported by this helper'. read() and write() call this resolver for every path they receive.
Source
Thrown at packages/coding-agent/src/eval/py/prelude.py:102
A `scheme://…` whose scheme has an injected on-disk root (e.g.
`local://`, via PI_EVAL_LOCAL_ROOTS) is rewritten under that root so it
lands where `read local://…` resolves — not a literal `local:/`
directory under the cwd (which `Path("local://x")` collapses to). Plain
paths pass through unchanged; any other `scheme://` is rejected."""
if not isinstance(path, str):
return Path(path)
match = _OMP_INTERNAL_URL_RE.match(path)
if not match:
return Path(path)
scheme = match.group(1).lower()
try:
roots = json.loads(os.environ.get("PI_EVAL_LOCAL_ROOTS") or "{}")
except (ValueError, TypeError):
roots = {}
root = roots.get(scheme) if isinstance(roots, dict) else None
if not root:
raise ValueError(f"Protocol paths are not supported by this helper: {path}")
relative = unquote(match.group(2).replace("\\", "/"))
# Mirror the host `path.resolve`/`resolveLocalUrlToPath`: normalize and
# make absolute WITHOUT realpath'ing symlinks (Path.resolve would turn
# /tmp into /private/tmp and diverge from the read-side resolution).
root_path = os.path.abspath(root)
if relative == "":
return Path(root_path)
rel_path = Path(relative)
if rel_path.is_absolute() or ".." in rel_path.parts:
raise ValueError(f"Unsafe {scheme}:// path (absolute or traversal): {path}")
resolved = os.path.abspath(os.path.join(root_path, relative))
if resolved != root_path and not resolved.startswith(root_path + os.sep):
raise ValueError(f"{scheme}:// path escapes its root: {path}")
return Path(resolved)
def read(path: str | Path, offset: int = 1, limit: int | None = None) -> str:
"""Read file or read-tool URI contents. offset/limit are 1-indexed lines."""
if _should_delegate_read(path):View on GitHub (pinned to 9690622007)
Solutions
- Set PI_EVAL_LOCAL_ROOTS to valid JSON mapping the scheme to a local root dir, e.g. {"omp": "/tmp/session-artifacts"}.
- Pass a plain local filesystem path to read()/write() instead of a scheme URI.
- Verify the scheme key casing matches what the harness injects into PI_EVAL_LOCAL_ROOTS.
Example fix
# before
content = read("s3://bucket/data.csv") # no 's3' root configured
# after
import os
os.environ.setdefault("PI_EVAL_LOCAL_ROOTS", '{"s3": "/tmp/s3-mirror"}')
content = read("s3://bucket/data.csv") # resolves to /tmp/s3-mirror/bucket/data.csv Defensive patterns
Strategy: validation
Validate before calling
import json, os
roots = json.loads(os.environ.get('PI_EVAL_LOCAL_ROOTS') or '{}')
scheme = path.split('://', 1)[0] if '://' in path else None
if scheme and scheme not in roots:
raise ValueError(f'Scheme {scheme}:// not configured in PI_EVAL_LOCAL_ROOTS') Type guard
def is_protocol_path(p): return '://' in str(p)
Try / catch
try:
content = read(path)
except ValueError as e:
if 'Protocol paths are not supported' in str(e):
content = read(local_fallback_path)
else:
raise Prevention
- Ensure the harness exports PI_EVAL_LOCAL_ROOTS before executing prelude code.
- Prefer plain local paths inside the eval sandbox over scheme URIs.
- Keep scheme keys in sync with the harness's URI scheme naming.
- Validate PI_EVAL_LOCAL_ROOTS parses as JSON at session start.
When it happens
Trigger: Calling prelude read()/write() with a URL-style path whose scheme (e.g. 's3://', 'gs://', or an 'omp://' tool URI) is missing from PI_EVAL_LOCAL_ROOTS, PI_EVAL_LOCAL_ROOTS unset or invalid JSON, or the scheme key having a different case/spelling than the map's keys.
Common situations: Model-generated code passing a tool-URI it saw in tool output instead of a local path; running the prelude outside the eval harness where PI_EVAL_LOCAL_ROOTS was never set; harness changes renaming a scheme.
Related errors
- Python kernel unavailable
- Python kernel unavailable
- Unsafe {scheme}:// path (absolute or traversal): {path}
- No session - output artifacts unavailable
- tool bridge is unavailable in this kernel
AI-assisted analysis of can1357/oh-my-pi@9690622007 (2026-08-31).
Data as JSON: /api/errors/00fd330d9c44d2e4.
Report an issue: GitHub.