{"record":{"id":"f704cfb4869fff50","repo":"can1357/oh-my-pi","slug":"protocol-paths-are-not-supported-by-this-helper-f704cf","errorCode":null,"errorMessage":"Protocol paths are not supported by this helper: #{path}","messagePattern":"Protocol paths are not supported by this helper: #(.+?)","errorType":"exception","errorClass":"RuntimeError","httpStatus":null,"severity":"error","filePath":"packages/coding-agent/src/eval/rb/prelude.rb","lineNumber":43,"sourceCode":"  end\n\n  # Map a helper path to a real filesystem path. A `scheme://…` whose scheme has\n  # an injected on-disk root (PI_EVAL_LOCAL_ROOTS, e.g. `local://`) is rewritten\n  # under that root; plain paths pass through; any other `scheme://` is rejected.\n  def __omp_resolve_path(path)\n    return path unless path.is_a?(String)\n    m = path.match(%r{\\A([a-z][a-z0-9+.\\-]*)://(.*)\\z}i)\n    return path unless m\n    scheme = m[1].downcase\n    roots =\n      begin\n        raw = ENV[\"PI_EVAL_LOCAL_ROOTS\"]\n        raw && !raw.empty? ? JSON.parse(raw) : {}\n      rescue StandardError\n        {}\n      end\n    root = roots.is_a?(Hash) ? roots[scheme] : nil\n    raise \"Protocol paths are not supported by this helper: #{path}\" if root.nil? || root.to_s.empty?\n    relative = __omp_url_decode(m[2].tr(\"\\\\\", \"/\"))\n    root_path = File.absolute_path(root.to_s)\n    return root_path if relative.empty?\n    if relative.start_with?(\"/\") || relative.split(\"/\").include?(\"..\")\n      raise \"Unsafe #{scheme}:// path (absolute or traversal): #{path}\"\n    end\n    resolved = File.absolute_path(File.join(root_path, relative))\n    unless resolved == root_path || resolved.start_with?(root_path + File::SEPARATOR)\n      raise \"#{scheme}:// path escapes its root: #{path}\"\n    end\n    resolved\n  end\n\n  # -------------------------------------------------------------------------\n  # Display + status\n  # -------------------------------------------------------------------------\n\n  def display(value)","sourceCodeStart":25,"sourceCodeEnd":61,"githubUrl":"https://github.com/can1357/oh-my-pi/blob/969062200754ea02cfac922e5ebb8c608c079e15/packages/coding-agent/src/eval/rb/prelude.rb#L25-L61","documentation":"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.","triggerScenarios":"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 {}).","commonSituations":"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.","solutions":["Set PI_EVAL_LOCAL_ROOTS to valid JSON mapping your scheme to a filesystem root, e.g. {\"local\": \"/home/me/eval-out\"}.","Use a scheme that already exists in PI_EVAL_LOCAL_ROOTS, or use a plain filesystem path instead of a protocol path.","Validate the env var parses as JSON before the run (a parse error is silently converted to {}).","Check the scheme spelling in your path matches the key in the roots map exactly."],"exampleFix":"# before: scheme never registered\nwrite(\"mydata://out.txt\", data)  # raises: Protocol paths are not supported\n\n# after: register the root (host sets this env) or use an allowed scheme\n# PI_EVAL_LOCAL_ROOTS='{\"mydata\": \"/tmp/eval-out\"}'\nwrite(\"mydata://out.txt\", data)","handlingStrategy":"validation","validationCode":"roots = begin\n  JSON.parse(ENV[\"PI_EVAL_LOCAL_ROOTS\"] || \"{}\")\nrescue StandardError\n  {}\nend\nscheme = path[/\\A([a-z][a-z0-9+.-]*):\\/\\//, 1]\nraise \"no local root for scheme #{scheme}\" if scheme && roots[scheme].nil?","typeGuard":"def protocol_path?(path)\n  %r{\\A[a-z][a-z0-9+.\\-]*://}.match?(path)\nend","tryCatchPattern":"begin\n  write(\"local://out.txt\", data)\nrescue RuntimeError => e\n  raise unless e.message.start_with?(\"Protocol paths are not supported\")\n  # fallback: write via a plain path or configure PI_EVAL_LOCAL_ROOTS first\n  File.write(\"/tmp/out.txt\", data)\nend","preventionTips":["Always set PI_EVAL_LOCAL_ROOTS with valid JSON before running eval cells that use protocol paths.","Keep scheme keys consistent between cell code and the roots map.","Prefer plain filesystem paths when no protocol mapping is configured.","Log/validate the parsed roots map at session start to catch JSON parse failures early."],"tags":["ruby","path-resolution","configuration","env-var"],"backgroundTag":"missing-env-var","analyzedSha":"969062200754ea02cfac922e5ebb8c608c079e15","analyzedAt":"2026-08-31T10:29:35.737Z","schemaVersion":2},"datasetVersion":"2026-08-31T14:17:45.589Z"}