musistudio/claude-code-router · critical · Error
ToolHub resolver could not connect to CCR Gateway at ${readi
Error message
ToolHub resolver could not connect to CCR Gateway at ${readinessUrl}: ${formatError(lastError)}. What it means
Thrown after the resolver exhausts its polling budget waiting for a local CCR Gateway (an OpenAI-compatible local proxy used by ToolHub resolve) to become ready at its readiness URL. The last observed connection error is included via formatError. This is a startup/dependency failure, not a query failure.
Source
Thrown at packages/core/src/mcp/toolhub-mcp.ts:1739
const timer = setTimeout(() => controller.abort(), 1000);
try {
await fetch(readinessUrl, {
headers: { authorization: `Bearer ${apiKey}` },
method: "GET",
signal: controller.signal
});
return;
} catch (error) {
lastError = error;
if (!isRetryableLocalResolverError(error)) {
return;
}
await delay(300);
} finally {
clearTimeout(timer);
}
}
throw new Error(`ToolHub resolver could not connect to CCR Gateway at ${readinessUrl}: ${formatError(lastError)}.`);
}
function localResolverReadinessUrl(baseURL: string): string | undefined {
let parsed: URL;
try {
parsed = new URL(baseURL);
} catch {
return undefined;
}
if (!isLoopbackHostname(parsed.hostname)) {
return undefined;
}
const base = baseURL.replace(/\/+$/g, "");
return `${base}/models`;
}
function isLoopbackHostname(hostname: string): boolean {
const normalized = hostname.trim().toLowerCase().replace(/^\[|\]$/g, "");View on GitHub (pinned to 99f24806c6)
Solutions
- Start the CCR Gateway and confirm it listens at the TOOLHUB_OPENAI_BASE_URL port
- curl the readiness URL printed in the message to verify it returns 200
- Increase the resolve timeoutMs so slow gateway startups can converge
- Point TOOLHUB_OPENAI_BASE_URL directly at OpenAI (or another ready endpoint) if you don't need the local gateway
Example fix
# before TOOLHUB_OPENAI_BASE_URL=http://localhost:9999/v1 # gateway not running # after ccr-gateway start & # or correct port curl http://localhost:9999/v1/health TOOLHUB_OPENAI_BASE_URL=http://localhost:9999/v1
Defensive patterns
Strategy: retry
Validate before calling
async function waitGateway(url: string, timeoutMs = 30000) {
const deadline = Date.now() + timeoutMs;
while (Date.now() < deadline) {
try { if ((await fetch(url)).ok) return; } catch {}
await new Promise(r => setTimeout(r, 300));
}
throw new Error(`Gateway not ready: ${url}`);
}
await waitGateway(readinessUrl); Try / catch
try {
await toolhub.resolve({ query });
} catch (e) {
if (e instanceof Error && e.message.includes("could not connect to CCR Gateway")) {
await startGateway(); await waitGateway(readinessUrl);
return await toolhub.resolve({ query });
}
throw e;
} Prevention
- Start and health-check the gateway as a supervised dependency before the app accepts traffic
- Bump resolve timeoutMs for slow gateway cold starts
When it happens
Trigger: waitForLocalResolverEndpoint retries against the readiness endpoint derived from TOOLHUB_OPENAI_BASE_URL until timeout, and every attempt fails (connection refused, DNS failure, TLS error), so the throw fires with the last error embedded.
Common situations: CCR Gateway not started or still booting when resolve() is called; wrong port in TOOLHUB_OPENAI_BASE_URL; gateway bound to a different interface; firewall blocking localhost connections; readiness URL path not exposed by an older gateway version.
Related errors
- Artifact origin is not the configured CCR gateway.
- Artifact URL does not use the CCR media artifact path.
- No available models. Configure at least one provider with a
- 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/d57d4dbf1f78d11f.
Report an issue: GitHub.