ruvnet/ruflo · error
Plugin ${name} already registered
Error message
Plugin ${name} already registered What it means
Thrown by EnhancedPluginRegistry.register() when a plugin with the same metadata.name is already present in the plugins map. The registry keys plugins strictly by name; the duplicate check runs right after interface validation and before max-plugins and version checks, so a duplicate is always rejected outright.
Source
Thrown at v3/@claude-flow/plugins/src/registry/enhanced-plugin-registry.ts:292
*/
async register(
plugin: IPlugin | PluginFactory,
config?: Partial<PluginConfig>
): Promise<void> {
// Resolve factory if needed
const resolvedPlugin = typeof plugin === 'function' ? await plugin() : plugin;
// Validate plugin
if (!validatePlugin(resolvedPlugin)) {
throw new Error('Invalid plugin: does not implement IPlugin interface');
}
const name = resolvedPlugin.metadata.name;
const version = resolvedPlugin.metadata.version;
// Check for duplicates
if (this.plugins.has(name)) {
throw new Error(`Plugin ${name} already registered`);
}
// Check max plugins
if (this.config.maxPlugins && this.plugins.size >= this.config.maxPlugins) {
throw new Error(`Maximum plugin limit (${this.config.maxPlugins}) reached`);
}
// Check core version compatibility
if (resolvedPlugin.metadata.minCoreVersion) {
if (!satisfiesVersion(`>=${resolvedPlugin.metadata.minCoreVersion}`, this.config.coreVersion)) {
throw new Error(
`Plugin ${name} requires core version >= ${resolvedPlugin.metadata.minCoreVersion}, ` +
`but current version is ${this.config.coreVersion}`
);
}
}
if (resolvedPlugin.metadata.maxCoreVersion) {
if (!satisfiesVersion(`<=${resolvedPlugin.metadata.maxCoreVersion}`, this.config.coreVersion)) {View on GitHub (pinned to fa13ee4ad6)
Solutions
- Unregister the existing plugin first (await registry.unregister(name)) or reuse the already-registered instance instead of re-registering
- Check registration state before calling register (via the registry's list API) and make registration idempotent in setup code
- Give each distinct plugin a unique metadata.name
Example fix
// before
await registry.register(pluginA); // name: 'logger'
await registry.register(pluginB); // also name: 'logger' -> throws
// after
await registry.register(pluginA);
const registered = (await registry.list()).map(p => p.metadata.name);
if (!registered.includes('logger')) {
await registry.register(pluginB);
}
// or: await registry.unregister('logger'); await registry.register(pluginB); Defensive patterns
Strategy: validation
Validate before calling
const name = plugin.metadata.name;
const registered = (await registry.list()).map(p => p.metadata.name);
if (registered.includes(name)) {
await registry.unregister(name); // or skip if already loaded
}
await registry.register(plugin); Try / catch
try {
await registry.register(plugin);
} catch (err) {
if (err instanceof Error && /already registered$/.test(err.message)) {
return; // idempotent bootstrap
}
throw err;
} Prevention
- Run registration from a single bootstrap function; never self-register on module import
- Check the registered set before registering, especially in tests and watch-mode
- Give every plugin a globally unique metadata.name (scope-prefix with team or project names)
When it happens
Trigger: Calling register(plugin) twice for the same plugin; registering two different plugins that both declare metadata.name 'my-plugin'; re-running bootstrap code (e.g. tests with a shared registry) that registers plugins again; a hot-reload path that registers the new version without unregistering the old one.
Common situations: Test files each importing a global registry fixture; watch-mode/HMR re-executing setup; plugin bundles that self-register on import being imported twice; copy-pasted plugins keeping the same name field.
Related errors
- Provider ${name} already registered
- Invalid plugin: does not implement IPlugin interface
- Maximum plugin limit (${this.config.maxPlugins}) reached
- Plugin ${name} requires core version >= ${resolvedPlugin.met
- Plugin ${name} requires core version <= ${resolvedPlugin.met
AI-assisted analysis of ruvnet/ruflo@fa13ee4ad6 (2026-08-18).
Data as JSON: /api/errors/228010af1e81cfcc.
Report an issue: GitHub.