Skip to content

[Bug]: file:// plugin dedup silently drops plugins when multiple share the same filename (e.g. index.js) #14304

@Aegis-commits

Description

@Aegis-commits

Description

When two or more plugins are loaded via file:// paths and their JS filenames are identical (e.g. both named index.js), deduplicatePlugins() silently drops all but one. No error or warning is logged.

Reproduction

// opencode.json
{
  "plugin": [
    "file:///home/user/plugin-a/dist/index.js",
    "file:///home/user/plugin-b/dist/index.js"
  ]
}

Expected: Both plugins load.
Actual: Only one loads (the later entry wins). The other is silently discarded.

Root Cause

getPluginName() extracts just the bare filename (without extension) for file:// URLs. Both paths resolve to canonical name "index". deduplicatePlugins() then treats them as the same plugin and keeps only the last one (reverse-order processing, last = highest priority).

Impact

This is a silent failure — no error, no warning, no log entry. The dropped plugin simply doesn't exist at runtime. This is especially likely during local plugin development where dist/index.js is the standard build output for most bundlers (bun, esbuild, rollup, etc.).

Suggested Fix

For file:// URLs, derive the canonical name from a more unique portion of the path rather than just the bare filename. Options:

  1. Use the parent directory name + filename (e.g. plugin-a/index"plugin-a")
  2. Use the full path as the canonical name for file:// entries
  3. At minimum, log a warning when dedup discards a file:// plugin

Workaround

Ensure each file:// plugin has a unique JS filename:

ln -sf /path/to/plugin/dist/index.js /path/to/plugin/dist/my-plugin.js
{
  "plugin": [
    "file:///home/user/plugin-a/dist/plugin-a.js",
    "file:///home/user/plugin-b/dist/index.js"
  ]
}

Environment

  • OpenCode (latest)
  • Linux x86_64
  • Multiple file:// plugins in config

Metadata

Metadata

Assignees

Labels

coreAnything pertaining to core functionality of the application (opencode server stuff)

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions