{"record":{"id":"3789a2185a319b2b","repo":"ruvnet/ruflo","slug":"no-available-provider-for-model-request-model","errorCode":null,"errorMessage":"No available provider for model ${request.model}","messagePattern":"No available provider for model (.+?)","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"v3/@claude-flow/plugins/src/providers/index.ts","lineNumber":231,"sourceCode":"      // Sort by success rate\n      candidates.sort((a, b) => {\n        const rateA = a.requestCount > 0 ? (a.requestCount - a.errorCount) / a.requestCount : 1;\n        const rateB = b.requestCount > 0 ? (b.requestCount - b.errorCount) / b.requestCount : 1;\n        return rateB - rateA;\n      });\n    }\n\n    return candidates[0]?.provider;\n  }\n\n  /**\n   * Execute a request with automatic provider selection and fallback.\n   */\n  async execute(request: LLMRequest): Promise<LLMResponse> {\n    const provider = this.getBest({ model: request.model });\n\n    if (!provider) {\n      throw new Error(`No available provider for model ${request.model}`);\n    }\n\n    return this.executeWithProvider(provider.definition.name, request);\n  }\n\n  /**\n   * Execute a request on a specific provider with retry.\n   */\n  async executeWithProvider(providerName: string, request: LLMRequest): Promise<LLMResponse> {\n    const entry = this.providers.get(providerName);\n    if (!entry) {\n      throw new Error(`Provider ${providerName} not found`);\n    }\n\n    const retryConfig = this.config.retryConfig!;\n    let lastError: Error | null = null;\n    let delay = retryConfig.initialDelayMs;\n","sourceCodeStart":213,"sourceCodeEnd":249,"githubUrl":"https://github.com/ruvnet/ruflo/blob/fa13ee4ad60ac2090b1480656eb233521790d640/v3/@claude-flow/plugins/src/providers/index.ts#L213-L249","documentation":"Thrown by LLMProviderRegistry.execute() when getBest({ model }) returns undefined. getBest filters registered providers by model support (definition.models must include the requested model), then drops any provider whose getRateLimitStatus().isLimited is true; if both filters remove every candidate, execute() has nothing to run on and throws.","triggerScenarios":"Calling execute({ model: 'gpt-4o', ... }) when no registered provider lists 'gpt-4o' in definition.models; every provider that supports the model is currently rate-limited (isLimited true); executing before any provider was registered; typo in the model string (case or suffix mismatch against definition.models).","commonSituations":"New model name deployed in the app before the provider definition was updated; all providers supporting the model hitting 429s so the rate-limit filter empties the candidate list; registering a provider with a narrow models array and then requesting a variant (e.g. 'gpt-4o-mini' not listed); tests that execute against an empty registry.","solutions":["Check with registry.getBest({ model }) (non-throwing) before execute(), or catch and inspect the registry's provider list to see which models are actually advertised","Add the requested model to the provider's definition.models array (or fix the typo) so the model filter matches","Wait for or reset rate-limit windows: providers excluded via getRateLimitStatus().isLimited become eligible again once the window clears","Register a fallback provider that supports the model so one limited provider does not empty the candidate set"],"exampleFix":"// before\nconst res = await registry.execute({ model: 'gpt-4o-mini', messages });\n// throws if no provider advertises that model\n\n// after\nif (!registry.getBest({ model: 'gpt-4o-mini' })) {\n  throw new Error(\n    `no provider for gpt-4o-mini; available models: ${\n      registry.listProviders().map(p => p.definition.models.join(',')).join('; ')\n    }`\n  );\n}\nconst res = await registry.execute({ model: 'gpt-4o-mini', messages });","handlingStrategy":"fallback","validationCode":"if (!registry.getBest({ model: request.model })) {\n  const available = registry.listProviders()\n    .flatMap(p => p.definition.models)\n    .join(', ');\n  throw new Error(`model ${request.model} has no provider; available models: ${available}`);\n}","typeGuard":"function hasProviderForModel(\n  registry: { getBest(o?: { model?: string }): unknown },\n  model: string\n): boolean {\n  return registry.getBest({ model }) !== undefined;\n}","tryCatchPattern":"try {\n  return await registry.execute(request);\n} catch (err) {\n  if (err instanceof Error && err.message.startsWith('No available provider')) {\n    // fall back to a model that IS registered\n    return registry.execute({ ...request, model: FALLBACK_MODEL });\n  }\n  throw err;\n}","preventionTips":["Boot-fail fast: assert getBest() for every model your app will request right after registering providers","Keep definition.models arrays in sync when adopting new model names","Register at least two providers per critical model so rate-limiting one does not empty the pool","Surface provider/model inventory in health checks to catch drift before requests do"],"tags":["llm-provider","no-candidates","rate-limit","registry","typescript"],"backgroundTag":"no-provider-available","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"}