{"record":{"id":"4ce09743097fe058","repo":"ruvnet/ruflo","slug":"provider-name-already-registered","errorCode":null,"errorMessage":"Provider ${name} already registered","messagePattern":"Provider (.+?) already registered","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"v3/@claude-flow/plugins/src/providers/index.ts","lineNumber":136,"sourceCode":"      costOptimization: false,\n      retryConfig: {\n        maxRetries: 3,\n        initialDelayMs: 1000,\n        maxDelayMs: 30000,\n        backoffMultiplier: 2,\n      },\n      ...config,\n    };\n  }\n\n  /**\n   * Register a provider.\n   */\n  register(provider: ILLMProvider): void {\n    const name = provider.definition.name;\n\n    if (this.providers.has(name)) {\n      throw new Error(`Provider ${name} already registered`);\n    }\n\n    const entry: ProviderEntry = {\n      provider,\n      registeredAt: new Date(),\n      requestCount: 0,\n      errorCount: 0,\n      totalTokensUsed: 0,\n      totalCost: 0,\n    };\n\n    this.providers.set(name, entry);\n    this.latencyTracking.set(name, []);\n    this.emit(PROVIDER_EVENTS.REGISTERED, { provider: name });\n  }\n\n  /**\n   * Unregister a provider.","sourceCodeStart":118,"sourceCodeEnd":154,"githubUrl":"https://github.com/ruvnet/ruflo/blob/fa13ee4ad60ac2090b1480656eb233521790d640/v3/@claude-flow/plugins/src/providers/index.ts#L118-L154","documentation":"Thrown by LLMProviderRegistry.register() when a provider whose definition.name is already present in the providers Map is registered a second time. The registry keys providers strictly by name, so duplicate names are treated as a programming/setup error rather than an overwrite.","triggerScenarios":"Calling registry.register(provider) twice with two ILLMProvider instances whose definition.name is identical (e.g. two 'openai' wrappers); hot-reload or repeated module import re-running setup code that registers the same provider; registering a custom provider that reuses a well-known name like 'anthropic'.","commonSituations":"Test suites that build a fresh registry per test but share a module-level provider list; HMR or watch-mode re-executing initialization; wrapping a stock provider under the same name instead of a distinct one; duplicate register calls left behind after a refactor.","solutions":["Call registry.unregister(name) (or build a fresh registry) before re-registering the same provider name","Guard registration with registry.get(name) - skip if the provider is already present","Give custom or wrapped providers a unique definition.name instead of shadowing a built-in name"],"exampleFix":"// before\nregistry.register(openaiProvider);\nregistry.register(customOpenai); // definition.name === 'openai' -> throws\n\n// after\nif (!registry.get('openai')) {\n  registry.register(openaiProvider);\n} else {\n  registry.unregister('openai');\n  registry.register(customOpenai);\n}","handlingStrategy":"validation","validationCode":"if (registry.get(provider.definition.name)) {\n  registry.unregister(provider.definition.name);\n}\nregistry.register(provider);","typeGuard":null,"tryCatchPattern":"try {\n  registry.register(provider);\n} catch (err) {\n  if (err instanceof Error && err.message.endsWith('already registered')) {\n    return; // idempotent setup: keep the existing registration\n  }\n  throw err;\n}","preventionTips":["Make registration idempotent: check registry.get(name) before register()","Derive every lookup from provider.definition.name, never a hand-typed string","In tests, use a fresh registry per case instead of a shared singleton that accumulates registrations"],"tags":["duplicate-registration","llm-provider","registry","typescript"],"backgroundTag":"duplicate-registration","analyzedSha":"fa13ee4ad60ac2090b1480656eb233521790d640","analyzedAt":"2026-08-18T21:34:22.708Z","contentChangedAt":"2026-08-18T21:34:22.708Z","schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}