musistudio/claude-code-router · error · Error
Resolve retrieval did not converge on any valid catalog tool
Error message
Resolve retrieval did not converge on any valid catalog tools.
What it means
Thrown when the ToolHub resolve loop produced zero valid catalog tool names and no AST-analyzer round ever ran. This is the pure-LLM failure path: the resolver model's response contained no usable tool selections before any AST refinement was attempted.
Source
Thrown at packages/core/src/mcp/toolhub-mcp.ts:1618
summary,
workflowSketch
})
: selectedToolNames.length === 0
? "Your current answer resolved to zero valid catalog tools. Call the tree-sitter tool on a revised TypeScript workflow sketch before answering."
: undefined;
if (refinementFeedback) {
messages.push(responseMessage);
messages.push({ role: "user", content: refinementFeedback });
continue;
}
break;
}
const selectedToolNames = uniqueStrings([...latestResolvedFromAnalyzer, ...llmSelectedNames]).slice(0, topK);
if (selectedToolNames.length === 0) {
throw new Error(didCallAnalyzer || analyzerCallCount > 0
? "Resolve retrieval did not converge on any valid catalog tools after AST refinement."
: "Resolve retrieval did not converge on any valid catalog tools.");
}
if (!didCallAnalyzer || analyzerCallCount === 0) {
referencedTokens = uniqueStrings([...referencedTokens, ...selectedToolNames]);
}
if (didCallAnalyzer && analyzerCallCount === 0) {
throw new Error("Resolve retrieval LLM did not complete an AST planning round.");
}
if (!summary) {
summary = didCallAnalyzer
? "Resolved a planned end-to-end tool bundle with AST-assisted retrieval."
: "Resolved a planned end-to-end tool bundle from the resolver model response.";
} else if (summary.toLowerCase().includes("no strong tool bundle match was found")) {
summary = "Resolved a candidate tool bundle after iterative AST refinement.";
}
return {
plannedSteps: plannedSteps.length > 0 ? plannedSteps : undefined,
referencedTokens,
selectedToolNames,View on GitHub (pinned to 99f24806c6)
Solutions
- Make the query more specific and domain-aligned with the catalog
- Switch to a resolver model that reliably emits tool calls (set TOOLHUB_OPENAI_MODEL)
- Check that the catalog actually contains candidate tools via search
- Retry — occasional non-deterministic empty model responses can occur
Example fix
// before
await toolhub.resolve({ query: "stuff" });
// after
await toolhub.resolve({ query: "transcribe an audio file to text with speaker labels", topK: 5 }); Defensive patterns
Strategy: retry
Validate before calling
const candidates = await toolhub.search({ query, topK: 3 });
if (candidates.results.length === 0) return { tools: [] }; // skip LLM resolve Try / catch
try {
return await toolhub.resolve({ query });
} catch (e) {
if (e instanceof Error && e.message.includes("did not converge")) {
await delay(1000);
return await toolhub.resolve({ query: clarify(query) }); // one retry with rephrase
}
throw e;
} Prevention
- Rewrite vague queries into tool-shaped requests before resolving
- Use a tool-calling-capable resolver model
When it happens
Trigger: resolve() ends with empty selection sets and didCallAnalyzer/analyzerCallCount are both falsy — the first LLM completion returned no tool calls or only invalid names.
Common situations: Ambiguous or off-domain query so the model selects nothing; a weak model that answers in prose instead of tool_calls; prompt/model misconfiguration producing empty responses.
Related errors
- Resolve retrieval did not converge on any valid catalog tool
- OpenAI resolve retrieval returned no assistant message.
- OpenAI resolve retrieval returned no assistant content or to
- ToolHub resolve query must be non-empty.
- ToolHub resolver requires TOOLHUB_OPENAI_API_KEY and TOOLHUB
AI-assisted analysis of musistudio/claude-code-router@99f24806c6 (2026-08-27).
Data as JSON: /api/errors/38ee20b66ba19dea.
Report an issue: GitHub.