musistudio/claude-code-router · warning
OpenRouter endpoints request is cooling down after failure
Error message
OpenRouter endpoints request is cooling down after failure (${Math.ceil(remainingMs / 1000)}s left): ${failure.message} What it means
The OpenRouter endpoints fetch implements a failure cooldown: after a failed request, subsequent calls for the same cache key fail fast with the remaining cooldown time instead of hammering the API. The original failure message is embedded.
Solutions
- Wait for the stated cooldown to elapse before retrying
- Fix the underlying failure (network, API key, rate limit) shown in the embedded message
- Cache endpoint results upstream so the call is not repeated per request
Example fix
// before retry(() => loadModelEndpoints(model), 5); // hammers cooldown // after const endpoints = await waitForCooldownThenLoad(model); // respects remainingMs
Defensive patterns
Strategy: retry
Validate before calling
null
Type guard
const isCooldownError = (e: unknown): boolean => e instanceof Error && e.message.includes("cooling down after failure"); Try / catch
try { return await loadModelEndpoints(model); } catch (e) { if (isCooldownError(e)) { const secs = Number(/\((\d+)s left\)/.exec(e.message)?.[1] ?? 0); await sleep((secs + 1) * 1000); return await loadModelEndpoints(model); } throw e; } Prevention
- Cache endpoint lookups per model
- Honor cooldown instead of tight retry loops
When it happens
Trigger: Calling loadModelEndpoints again within endpointFailureCooldownMs after a previous failure for the same model+apiRoot key.
Common situations: Retry loops or multiple concurrent completions calling endpoints for the same model right after a network/HTTP failure.
Related errors
- [fusion-vision] Failed to publish lightweight usage event
- OpenRouter discount routing skipped
- OpenRouter endpoints request failed
- OpenRouter endpoints request timed out after
- OpenRouter model id must be author/slug
AI-assisted analysis of musistudio/claude-code-router@99f24806c6 (2026-08-27).
Data as JSON: /api/errors/cef46fb06f8998be.
Report an issue: GitHub.
Appendix: source
Thrown at packages/core/src/plugins/built-ins/openrouter-discount-provider-router.ts:311
async function loadModelEndpoints(
provider: GatewayProviderConfig,
model: string,
settings: OpenRouterDiscountRoutingSettings
): Promise<unknown[]> {
const apiRoot = openRouterApiRoot(provider);
const cacheKey = `${apiRoot}:${model}`;
const cached = endpointCache.get(cacheKey);
const now = Date.now();
if (cached && now - cached.fetchedAt < settings.endpointTtlMs) {
return cached.endpoints;
}
const failure = endpointFailureCache.get(cacheKey);
if (failure) {
const cooldownAge = now - failure.failedAt;
if (cooldownAge < endpointFailureCooldownMs) {
const remainingMs = endpointFailureCooldownMs - cooldownAge;
throw new Error(`OpenRouter endpoints request is cooling down after failure (${Math.ceil(remainingMs / 1000)}s left): ${failure.message}`);
}
endpointFailureCache.delete(cacheKey);
}
const inflight = endpointInflight.get(cacheKey);
if (inflight) {
return inflight;
}
const [author, ...slugParts] = model.split("/");
const slug = slugParts.join("/");
if (!author || !slug) {
throw new Error(`OpenRouter model id must be author/slug: ${model}`);
}
const url = `${trimRight(apiRoot, "/")}/api/v1/models/${encodeURIComponent(author)}/${encodeURIComponent(slug)}/endpoints`;
const promise = fetchModelEndpoints(url).then((endpoints) => {
endpointFailureCache.delete(cacheKey);
if (endpoints.length > 0) {View on GitHub (pinned to 99f24806c6)