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

  1. Set PI_EVAL_LOCAL_ROOTS to valid JSON mapping the scheme to a local root dir, e.g. {"omp": "/tmp/session-artifacts"}.
  2. Pass a plain local filesystem path to read()/write() instead of a scheme URI.
  3. 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

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


AI-assisted analysis of can1357/oh-my-pi@9690622007 (2026-08-31). Data as JSON: /api/errors/00fd330d9c44d2e4. Report an issue: GitHub.