ruvnet/ruflo · error

Plugin name mismatch: expected ${name}, got ${resolved.metad

Error message

Plugin name mismatch: expected ${name}, got ${resolved.metadata.name}

What it means

Thrown by EnhancedPluginRegistry.reload(name, newPlugin) when the replacement passes validation but its metadata.name differs from the name argument. reload is an in-place hot swap keyed by name (it removes and re-adds the same node in the dependency graph), so the replacement must keep the identity of the plugin it replaces; a different name would silently change who depends on whom.

Source

Thrown at v3/@claude-flow/plugins/src/registry/enhanced-plugin-registry.ts:560

    let state: unknown;
    if (options?.preserveState && (entry.plugin as any).getState) {
      state = await (entry.plugin as any).getState();
    }

    // Shutdown old plugin
    if (entry.plugin.state === 'initialized') {
      await entry.plugin.shutdown();
    }

    // Resolve and validate new plugin
    const resolved = typeof newPlugin === 'function' ? await newPlugin() : newPlugin;
    if (!validatePlugin(resolved)) {
      throw new Error('Invalid plugin replacement');
    }

    // Verify same name
    if (resolved.metadata.name !== name) {
      throw new Error(`Plugin name mismatch: expected ${name}, got ${resolved.metadata.name}`);
    }

    // Update dependency graph
    const dependencies = this.parseDependencies(resolved.metadata.dependencies);
    this.dependencyGraph.removePlugin(name);
    this.dependencyGraph.addPlugin(name, resolved.metadata.version, dependencies);

    // Initialize new plugin
    const context = this.createPluginContext(entry);
    const timeout = options?.timeout ?? this.config.loadTimeout ?? 30000;

    await Promise.race([
      resolved.initialize(context),
      new Promise<never>((_, reject) =>
        setTimeout(() => reject(new Error('Hot reload timeout')), timeout)
      ),
    ]);

View on GitHub (pinned to fa13ee4ad6)

Solutions

  1. Set the replacement's metadata.name to exactly the registered plugin's name before reload
  2. If you intend a rename, do it explicitly: unregister the old name and register the new plugin (updating dependents' declarations accordingly)
  3. Assert the name matches in your build or verification step before shipping the hot-swap artifact

Example fix

// before
await registry.reload('logger', loggerV2); // loggerV2.metadata.name === 'logger-v2' -> throws

// after
loggerV2.metadata.name = 'logger'; // keep identity for hot-swap
await registry.reload('logger', loggerV2);
Defensive patterns

Strategy: validation

Validate before calling

const resolved = typeof newPlugin === 'function' ? await newPlugin() : newPlugin;
if (resolved.metadata.name !== name) {
  throw new Error(
    `reload target '${name}' but replacement is '${resolved.metadata.name}'; ` +
    'use unregister+register for renames'
  );
}
await registry.reload(name, resolved);

Try / catch

try {
  await registry.reload(name, newPlugin);
} catch (err) {
  if (err instanceof Error && err.message.startsWith('Plugin name mismatch')) {
    // intended rename: fall back to an explicit swap
    await registry.unregister(name);
    await registry.register(resolved);
  } else {
    throw err;
  }
}

Prevention

When it happens

Trigger: reload('logger', newPlugin) where newPlugin.metadata.name is 'logger-v2'; copy-pasting a plugin and forgetting to update metadata.name before hot-swapping it in; reload tooling passing a file or alias name that differs from the replacement's internal name.

Common situations: Major-version plugin rewrite that renames the plugin; build tooling generating plugins with suffixed names; CI hot-reload of a differently-named artifact.

Related errors


AI-assisted analysis of ruvnet/ruflo@fa13ee4ad6 (2026-08-18). Data as JSON: /api/errors/cd29b2e108c55a53. Report an issue: GitHub.