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

  1. Wait for the stated cooldown to elapse before retrying
  2. Fix the underlying failure (network, API key, rate limit) shown in the embedded message
  3. 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

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


AI-assisted analysis of musistudio/claude-code-router@99f24806c6 (2026-08-27). Data as JSON: /api/errors/cef46fb06f8998be. Report an issue: GitHub.