Skip to content

bug: plugin fails to load in OpenCode with "path must be a string or a file descriptor" / "Received an instance of Object" #596

Description

@imaadd05

Problem

Loading the ponytail OpenCode plugin (@dietrichgebert/ponytail, installed via "plugin": ["@dietrichgebert/ponytail"] in opencode.json) fails at plugin-load time. OpenCode logs:

message="failed to load plugin" path=@dietrichgebert/ponytail error="path must be a string or a file descriptor"

and, in later runs (same install, no config change), a differently-worded variant of what looks like the same underlying failure:

message="failed to load plugin" path=@dietrichgebert/ponytail error="The \"path\" argument must be of type string or an instance of Buffer or URL. Received an instance of Object"

Environment

  • @dietrichgebert/ponytail 4.8.4 (installed via OpenCode's git/npm plugin loader, ~/.cache/opencode/packages/@dietrichgebert/ponytail)
  • OpenCode 1.17.18 (a downstream fork, but this is plugin-loading, not fork-specific behavior)
  • Node v26.4.0 / Bun 1.3.14, macOS (Darwin 25.5.0, arm64)

What I ruled out

I dug into this while diagnosing an unrelated OpenCode bug and don't want to leave you without a lead, so here's what I checked:

  • This looked like it could be a recurrence of Bug: Test suite fails on Node.js versions < 20.11.0 due to import.meta.dirname usage #156 (import.meta.dirname unavailable → path.join(undefined, ...)), but that pattern is fully gone from the 4.8.4 source (grep -rn "import.meta.dirname" over the installed package returns nothing), and the second error text explicitly says "Received an instance of Object", not undefined — so it's a different failure: something is passing a non-path object where fs/path expects a string/Buffer/URL.
  • Manually import()-ing .opencode/plugins/ponytail.mjs and invoking the default export directly with { client: undefined } succeeds fine and returns all three hooks (config, experimental.chat.system.transform, command.execute.before) — so the crash isn't in the module's top-level factory body executing in isolation. It must be triggered by something OpenCode's real plugin-loader passes in (e.g. the actual PluginInput/client shape), which I didn't have on hand to fully reproduce outside the running app.
  • Notably, despite this load failure, the plugin's experimental.chat.system.transform hook still appears to fire successfully on chat turns (it's what caused the OpenCode-side bug I was diagnosing) — so whatever throws seems to happen either during a different hook invocation, or asynchronously after registration succeeds, rather than blocking config load entirely.

Suggested next step

Since the crash didn't reproduce with a bare {client: undefined} input, the likely spot is code paths that consume more of PluginInput than just client — worth auditing anywhere a path.*/fs.* call could receive a client/config/URL-like object instead of a string (e.g. if a value from OpenCode's client/config object ever flows into a path.join/fs.readFileSync call unchecked).

Happy to share the exact opencode.json plugin config or more log context if useful.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions