musistudio/claude-code-router · warning · Error
ToolHub resolve query must be non-empty.
Error message
ToolHub resolve query must be non-empty.
What it means
Thrown by the ToolHub resolve flow when the natural-language query, after trimming, is empty. The resolver cannot search a catalog without a query, so this is a fast-fail input validation before any network or LLM work occurs.
Source
Thrown at packages/core/src/mcp/toolhub-mcp.ts:1476
class OpenAiToolHubSearchAgent {
private readonly analyzer = new ToolReferenceAnalyzer();
constructor(private readonly config: {
openAiApiKey?: string;
openAiBaseUrl?: string;
openAiModel?: string;
}) {}
async search(input: {
catalog: SearchCatalogItem[];
code?: string;
query: string;
timeoutMs?: number;
topK?: number;
}): Promise<SearchResult> {
const query = input.query.trim();
if (!query) {
throw new Error("ToolHub resolve query must be non-empty.");
}
const apiKey = this.config.openAiApiKey || env("TOOLHUB_OPENAI_API_KEY");
const baseURL = this.config.openAiBaseUrl || env("TOOLHUB_OPENAI_BASE_URL") || "https://api.openai.com/v1";
const model = this.config.openAiModel || env("TOOLHUB_OPENAI_MODEL");
if (!apiKey || !model) {
throw new Error("ToolHub resolver requires TOOLHUB_OPENAI_API_KEY and TOOLHUB_OPENAI_MODEL.");
}
const topK = normalizeTopK(input.topK);
const timeoutMs = normalizeSearchTimeout(input.timeoutMs);
const deadlineAt = Date.now() + timeoutMs;
await waitForLocalResolverEndpoint(baseURL, apiKey, timeoutMs);
const client = new OpenAI({ apiKey, baseURL });
const messages: SearchMessage[] = [
{
role: "user",
content: JSON.stringify({
context: input.code ?? "",View on GitHub (pinned to 99f24806c6)
Solutions
- Ensure the caller passes a non-empty, meaningful natural-language query
- Trim and check user input before calling resolve
- Add an upstream UI/CLI guard rejecting empty prompts
Example fix
// before
await toolhub.resolve({ query: userPrompt /* may be "" */ });
// after
const q = (userPrompt ?? "").trim();
if (!q) throw new Error("Prompt is required");
await toolhub.resolve({ query: q }); Defensive patterns
Strategy: validation
Validate before calling
const query = String(input.query ?? "").trim();
if (!query) {
throw new Error("Query is required");
}
await toolhub.resolve({ query }); Type guard
const hasNonEmptyQuery = (q: unknown): q is string => typeof q === "string" && q.trim().length > 0;
Prevention
- Trim user input at the boundary (CLI/UI) and reject empty prompts
- Type resolve input as { query: string } so empties surface at compile/test time
When it happens
Trigger: Calling the ToolHub resolve API with a query of "", " ", or a value that trims to empty (undefined coerced/typed as empty string).
Common situations: Passing an unvalidated user prompt straight through; template strings that interpolate undefined; whitespace-only input from a CLI arg or form field.
Related errors
- The CCR artifact endpoint returned a non-media content type.
- The CCR media artifact exceeds the inline preview size limit
- Compressed CCR media artifacts are not accepted for inline p
- The CCR artifact response was empty.
- The CCR artifact response length did not match its headers.
AI-assisted analysis of musistudio/claude-code-router@99f24806c6 (2026-08-27).
Data as JSON: /api/errors/8c8f9540f8f4fce9.
Report an issue: GitHub.