{"record":{"id":"6425c137a67f9f92","repo":"ruvnet/ruflo","slug":"no-suitable-models-available-for-request","errorCode":null,"errorMessage":"No suitable models available for request","messagePattern":"No suitable models available for request","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"v3/@claude-flow/integration/src/multi-model-router.ts","lineNumber":518,"sourceCode":"    // Filter models by capabilities\n    let candidateModels = this.filterByCapabilities(request.requiredCapabilities);\n\n    // Filter by health (exclude unhealthy providers)\n    candidateModels = this.filterByHealth(candidateModels);\n\n    // Apply routing rules if in rule-based mode\n    if (this.config.mode === 'rule-based') {\n      const ruleResult = this.applyRules(request, candidateModels);\n      if (ruleResult) {\n        return ruleResult;\n      }\n    }\n\n    // Score and rank candidates\n    const scoredCandidates = this.scoreModels(request, candidateModels);\n\n    if (scoredCandidates.length === 0) {\n      throw new Error('No suitable models available for request');\n    }\n\n    // Select best candidate\n    const best = scoredCandidates[0];\n    const model = this.models.get(best.modelId)!;\n\n    const result: RoutingResult = {\n      provider: model.provider,\n      model: model.id,\n      reason: this.generateReason(best),\n      estimatedCost: best.estimatedCost,\n      estimatedLatency: model.latencyMs,\n      qualityScore: model.qualityScore,\n      alternatives: scoredCandidates.slice(1, 4).map(c => ({\n        provider: this.models.get(c.modelId)!.provider,\n        model: c.modelId,\n        estimatedCost: c.estimatedCost,\n      })),","sourceCodeStart":500,"sourceCodeEnd":536,"githubUrl":"https://github.com/ruvnet/ruflo/blob/fa13ee4ad60ac2090b1480656eb233521790d640/v3/@claude-flow/integration/src/multi-model-router.ts#L500-L536","documentation":"Thrown by MultiModelRouter when routing a completion request (v3/@claude-flow/integration/src/multi-model-router.ts:518): after filtering candidates by required capabilities and scoring them, zero models remain. Either no registered model satisfies the request's constraints (context window, capabilities, budget, latency), or rule-based mode produced no matching rule and all candidates were filtered out.","triggerScenarios":"Requesting tools support when every registered model has supportsTools: false; asking for a context window larger than any model's; a maxCost/maxLatency budget that filters out all providers; an empty or failed model registration (no models in this.models); responseFormat 'json' when no model supports JSON mode.","commonSituations":"Only a cheap/legacy provider registered while the request needs tool calling; budget env vars set too aggressively (MAX_COST_PER_REQUEST=0); model registry misconfigured after provider outages removed models; capability metadata stale after an SDK upgrade.","solutions":["Inspect the request's constraints (requiredCapabilities, contextWindow, maxCost, maxLatency) and relax the one that eliminates all candidates.","Register at least one model that satisfies the hard requirements — verify each model's capability flags in the registry.","If in rule-based mode, add a catch-all rule so unmatched requests still get a default model instead of falling through to scoring with an empty set.","Check that model registration succeeded (log this.models.size) — a silent provider init failure leaves the router empty."],"exampleFix":"// before\nconst res = await router.route(request); // request requires tools, no model supports them\n\n// after\nconst capable = [...router.models.values()].filter((m) => m.supportsTools);\nif (capable.length === 0) throw new Error('register a tool-capable model first');\nconst res = await router.route({ ...request, requiredCapabilities: { supportsTools: true } });","handlingStrategy":"fallback","validationCode":"const capable = [...router.models.values()].filter((m) =>\n  m.capabilities.supportsTools || !request.tools\n);\nif (capable.length === 0) {\n  // drop optional constraints or register a capable model before routing\n  request = { ...request, tools: undefined };\n}","typeGuard":"function requestIsSatisfiable(models: Model[], req: LLMRequest): boolean {\n  return models.some((m) =>\n    (!req.tools || m.supportsTools) &&\n    (!req.responseFormat || req.responseFormat !== 'json' || m.supportsJson) &&\n    m.contextWindow >= estimateTokens(req)\n  );\n}","tryCatchPattern":"try {\n  return await router.complete(request);\n} catch (e) {\n  if ((e as Error).message === 'No suitable models available for request') {\n    return router.complete(relaxConstraints(request)); // drop maxCost/latency or capability extras\n  }\n  throw e;\n}","preventionTips":["Keep at least one high-capability model registered as a catch-all.","Validate capability requirements against the registry at startup, not at request time.","Add a default routing rule in rule-based mode so unmatched requests never reach empty scoring."],"tags":["model-routing","no-capable-provider","filtering","llm"],"backgroundTag":"no-capable-provider","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"}