{"record":{"id":"fe7c820be8d1718f","repo":"ruvnet/ruflo","slug":"plugin-name-not-found","errorCode":null,"errorMessage":"Plugin ${name} not found","messagePattern":"Plugin (.+?) not found","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"v3/@claude-flow/plugins/src/registry/enhanced-plugin-registry.ts","lineNumber":351,"sourceCode":"    // Store entry\n    const entry: PluginEntry = {\n      plugin: resolvedPlugin,\n      config: pluginConfig,\n      loadTime: new Date(),\n    };\n\n    this.plugins.set(name, entry);\n    this.eventBus.emit(PLUGIN_EVENTS.LOADED, { plugin: name });\n    this.logger.info(`Plugin registered: ${name} v${version}`);\n  }\n\n  /**\n   * Unregister a plugin with dependency checking.\n   */\n  async unregister(name: string, options?: UnregisterOptions): Promise<void> {\n    const entry = this.plugins.get(name);\n    if (!entry) {\n      throw new Error(`Plugin ${name} not found`);\n    }\n\n    // Check dependents\n    const dependents = this.dependencyGraph.getDependents(name);\n\n    if (dependents.length > 0) {\n      if (options?.cascade) {\n        // Unload dependents first (in reverse order)\n        const order = this.dependencyGraph.getRemovalOrder(name);\n        for (const dep of order) {\n          if (dep !== name) {\n            await this.shutdownPlugin(dep);\n            this.removePluginFromGraph(dep);\n          }\n        }\n      } else if (options?.force) {\n        this.logger.warn(`Force removing ${name}, breaking: ${dependents.join(', ')}`);\n      } else {","sourceCodeStart":333,"sourceCodeEnd":369,"githubUrl":"https://github.com/ruvnet/ruflo/blob/fa13ee4ad60ac2090b1480656eb233521790d640/v3/@claude-flow/plugins/src/registry/enhanced-plugin-registry.ts#L333-L369","documentation":"Thrown by EnhancedPluginRegistry.unregister(name) as its first statement: a plain plugins.get(name) lookup that missed. Nothing else runs before it, so this error means exactly that no plugin with that name is registered on this registry instance (never registered, already unregistered, or name mismatch).","triggerScenarios":"Calling unregister('my-plugin') when the plugin registered under a different metadata.name; unregistering during shutdown after it was already unregistered (double-teardown); typo or casing differences between the registration name and the teardown call.","commonSituations":"Cleanup code in tests running against a fresh registry; shutdown handlers racing with a prior unregister; name drift between the plugin package's metadata and hard-coded teardown strings.","solutions":["List registered plugins (registry list API or logs) and use the exact metadata.name","Make teardown idempotent: only unregister when the plugin is actually present","Source the name from the plugin object's metadata rather than a duplicated string literal"],"exampleFix":"// before\nawait registry.unregister('logger-plugin'); // registered as 'logger' -> throws\n\n// after\nconst registered = (await registry.list()).map(p => p.metadata.name);\nif (registered.includes('logger')) {\n  await registry.unregister('logger');\n}","handlingStrategy":"validation","validationCode":"const registered = new Set((await registry.list()).map(p => p.metadata.name));\nif (!registered.has(name)) {\n  logger.debug(`unregister skipped: '${name}' not registered`);\n} else {\n  await registry.unregister(name);\n}","typeGuard":null,"tryCatchPattern":"try {\n  await registry.unregister(name);\n} catch (err) {\n  if (err instanceof Error && err.message.endsWith('not found')) return; // idempotent teardown\n  throw err;\n}","preventionTips":["Make teardown idempotent: tolerate 'not found' on unregister","Take unregister names from the same metadata.name used at registration","Run teardown once (leaf plugins first) from a single shutdown path"],"tags":["plugin-not-found","plugin-registry","typescript"],"backgroundTag":"plugin-not-found","analyzedSha":"fa13ee4ad60ac2090b1480656eb233521790d640","analyzedAt":"2026-08-18T21:34:22.708Z","contentChangedAt":"2026-08-18T21:34:22.708Z","schemaVersion":2},"datasetVersion":"2026-09-14T00:17:10.932Z"}