Skip to content

plugin: configured local plugin file paths silently dropped since #46105 #46551

Description

@luisherranz

Summary

Since #46105 (2026-08-30), configured plugin entries that resolve to an absolute file path are silently dropped with only a level=WARN log line ("configured plugin path must be a directory"), while the plugins docs still document file paths as valid config entries. Upgrading silently disables local plugins.

Environment

  • opencode version: v2 branch (source build at 71779ae5de, channel local)
  • OS: Darwin 25.6.0 (darwin arm64)
  • Terminal: Unavailable (headless server context)
  • Shell: /bin/zsh
  • Install/channel: source build (channel local), v2 line
  • Active plugins: two local plugins configured by absolute path (see Reproduction)

Reproduction

  1. Configure a local plugin by absolute file path:
    {
      "plugins": [
        "/Users/me/opencode-plugin/plugin.js"
      ]
    }
    where plugin.js has a default export (export default { id, setup }). This worked before 2026-08-30.
  2. Start opencode serve (or any server that loads plugins).
  3. The plugin is not loaded. The server log contains:
    level=WARN message="configured plugin path must be a directory" target=/Users/me/opencode-plugin/plugin.js
    
    No error is surfaced to the user; the plugin simply disappears (its models, tools, and skills are gone).

Expected Behavior

Either:

  • Configured file paths keep working (resolve the file directly as the plugin entrypoint, as before feat(plugin): add typed rpc and custom events #46105), or
  • The docs are updated to remove file-path examples, and the drop is surfaced loudly (config error / visible warning) instead of a WARN log line — silently losing plugins on upgrade is the worst outcome.

Actual Behavior

packages/core/src/config/plugin/source.ts (since 6a2c3e91c7, #46105) drops any configured target that fs.isFile with the warning "configured plugin path must be a directory" and returns Option.none, so the plugin is never loaded. This also affects relative file paths (../shared/plugin.ts) and file:// entries pointing at files, which resolve to absolute paths before the check.

Additional Context

  • The docs still show file paths as valid: packages/www/src/docs/content/plugins.mdx examples include "../shared/plugin.ts", "/absolute/path/plugin.ts", and "file:///home/me/plugins/local". config.mdx says "Load plugins from packages or local plugin directories" and only shows directory examples.
  • Directory targets only work when the directory contains an index.ts/index.js (PluginSourceDirectory.entrypoint); a directory without one is also dropped ("configured plugin directory has no index entrypoint").
  • Workaround: point the config at the plugin directory and add an index.js re-exporting the plugin file. Package (npm/Git) plugin entries are unaffected because they resolve through package.json exports/main.
  • This bit in production on a self-hosted instance: both configured plugins (a subscription auth plugin and a pipeline plugin) silently vanished after rebasing onto the v2 branch that includes feat(plugin): add typed rpc and custom events #46105; models provided by the subscription plugin disappeared from the catalog.

Metadata

Metadata

Assignees

Labels

No labels
No labels

Type

No type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions