What happens
The loader derives a plugin's id from the module basename. The natural out-of-tree convention is <name>/plugin.js, so every plugin derives the id plugin, and the (correct) duplicate-id guard refuses to boot until each entry carries an explicit id.
Repro
createServer({ plugins: [
{ module: 'relay/plugin.js', prefix: '/relay' },
{ module: 'webrtc/plugin.js', prefix: '/webrtc' },
] })
// → duplicate plugin id 'plugin'
Evidence
All 32 plugins in https://github.com/JavaScriptSolidServer/plugins hit this; compose.test.js and serve.js there carry 32 hand-written id: fields solely to dodge it. See REPORT.md ("Five loader/core bugs", #1).
Suggested fix
When the basename is generic (plugin, index), derive the id from the parent directory: relay/plugin.js → relay. Backward-compatible (explicit id still wins); removes the most common plugin-author footgun.
What happens
The loader derives a plugin's id from the module basename. The natural out-of-tree convention is
<name>/plugin.js, so every plugin derives the idplugin, and the (correct) duplicate-id guard refuses to boot until each entry carries an explicitid.Repro
Evidence
All 32 plugins in https://github.com/JavaScriptSolidServer/plugins hit this;
compose.test.jsandserve.jsthere carry 32 hand-writtenid:fields solely to dodge it. See REPORT.md ("Five loader/core bugs", #1).Suggested fix
When the basename is generic (
plugin,index), derive the id from the parent directory:relay/plugin.js→relay. Backward-compatible (explicitidstill wins); removes the most common plugin-author footgun.