can1357/oh-my-pi · error · RuntimeError

Protocol paths are not supported by this helper: #{path}

Error message

Protocol paths are not supported by this helper: #{path}

What it means

The Ruby eval prelude's `__omp_resolve_path` maps `scheme://path` URLs (e.g. `local://out.txt`) to real filesystem paths using roots provided via the `PI_EVAL_LOCAL_ROOTS` environment variable (a JSON object keyed by scheme). It raises this error when the URL's scheme has no corresponding root entry (nil or empty), i.e. protocol-style paths are only supported for schemes that were explicitly configured as local roots.

Source

Thrown at packages/coding-agent/src/eval/rb/prelude.rb:43

  end

  # Map a helper path to a real filesystem path. A `scheme://…` whose scheme has
  # an injected on-disk root (PI_EVAL_LOCAL_ROOTS, e.g. `local://`) is rewritten
  # under that root; plain paths pass through; any other `scheme://` is rejected.
  def __omp_resolve_path(path)
    return path unless path.is_a?(String)
    m = path.match(%r{\A([a-z][a-z0-9+.\-]*)://(.*)\z}i)
    return path unless m
    scheme = m[1].downcase
    roots =
      begin
        raw = ENV["PI_EVAL_LOCAL_ROOTS"]
        raw && !raw.empty? ? JSON.parse(raw) : {}
      rescue StandardError
        {}
      end
    root = roots.is_a?(Hash) ? roots[scheme] : nil
    raise "Protocol paths are not supported by this helper: #{path}" if root.nil? || root.to_s.empty?
    relative = __omp_url_decode(m[2].tr("\\", "/"))
    root_path = File.absolute_path(root.to_s)
    return root_path if relative.empty?
    if relative.start_with?("/") || relative.split("/").include?("..")
      raise "Unsafe #{scheme}:// path (absolute or traversal): #{path}"
    end
    resolved = File.absolute_path(File.join(root_path, relative))
    unless resolved == root_path || resolved.start_with?(root_path + File::SEPARATOR)
      raise "#{scheme}:// path escapes its root: #{path}"
    end
    resolved
  end

  # -------------------------------------------------------------------------
  # Display + status
  # -------------------------------------------------------------------------

  def display(value)

View on GitHub (pinned to 9690622007)

Solutions

  1. Set PI_EVAL_LOCAL_ROOTS to valid JSON mapping your scheme to a filesystem root, e.g. {"local": "/home/me/eval-out"}.
  2. Use a scheme that already exists in PI_EVAL_LOCAL_ROOTS, or use a plain filesystem path instead of a protocol path.
  3. Validate the env var parses as JSON before the run (a parse error is silently converted to {}).
  4. Check the scheme spelling in your path matches the key in the roots map exactly.

Example fix

# before: scheme never registered
write("mydata://out.txt", data)  # raises: Protocol paths are not supported

# after: register the root (host sets this env) or use an allowed scheme
# PI_EVAL_LOCAL_ROOTS='{"mydata": "/tmp/eval-out"}'
write("mydata://out.txt", data)
Defensive patterns

Strategy: validation

Validate before calling

roots = begin
  JSON.parse(ENV["PI_EVAL_LOCAL_ROOTS"] || "{}")
rescue StandardError
  {}
end
scheme = path[/\A([a-z][a-z0-9+.-]*):\/\//, 1]
raise "no local root for scheme #{scheme}" if scheme && roots[scheme].nil?

Type guard

def protocol_path?(path)
  %r{\A[a-z][a-z0-9+.\-]*://}.match?(path)
end

Try / catch

begin
  write("local://out.txt", data)
rescue RuntimeError => e
  raise unless e.message.start_with?("Protocol paths are not supported")
  # fallback: write via a plain path or configure PI_EVAL_LOCAL_ROOTS first
  File.write("/tmp/out.txt", data)
end

Prevention

When it happens

Trigger: Calling read/write (which delegate to __omp_resolve_path) with a `scheme://...` path where PI_EVAL_LOCAL_ROOTS has no mapping for that scheme, the env var is unset/empty, or its JSON failed to parse (falls back to {}).

Common situations: Using a custom `mydata://file` scheme that was never registered; forgetting to set PI_EVAL_LOCAL_ROOTS before running the cell; malformed JSON in PI_EVAL_LOCAL_ROOTS (silently swallowed → empty roots); typo in the scheme key.

Understand the failure class

Background: "environment variable is not set" and "Missing keys in environment" errors: what missing required env var messages mean and how to fix them — this error's family across 28 libraries.

Related errors


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