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.
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)
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
- OpenRouter model id must be author/slug: ${model}
- OpenRouter endpoints request timed out after ${endpointFetch
- OpenRouter endpoints request failed (${response.status}): ${
- OpenRouter providers request failed (${response.status}): ${
- OpenRouter model id must be author/slug: ${model}
AI-assisted analysis of musistudio/claude-code-router@99f24806c6 (2026-08-27).
Data as JSON: /api/errors/cef46fb06f8998be.
Report an issue: GitHub.