musistudio/claude-code-router · error

OpenRouter endpoints request failed (${response.status}): ${

Error message

OpenRouter endpoints request failed (${response.status}): ${text.slice(0, 200)}

What it means

A non-2xx response from OpenRouter's model endpoints API surfaces as this error, including the HTTP status and first 200 chars of the body for diagnosis. The failure is then cached to trigger the cooldown for subsequent calls.

Source

Thrown at packages/core/src/plugins/built-ins/openrouter-discount-provider-router.ts:369

    controller.abort(new Error(`OpenRouter endpoints request timed out after ${endpointFetchTimeoutMs}ms`));
  }, endpointFetchTimeoutMs);
  timer.unref?.();

  let response: Response;
  try {
    response = await fetch(url, { signal: controller.signal });
  } catch (error) {
    if (controller.signal.aborted) {
      throw new Error(`OpenRouter endpoints request timed out after ${endpointFetchTimeoutMs}ms`);
    }
    throw error;
  } finally {
    clearTimeout(timer);
  }

  if (!response.ok) {
    const text = await response.text().catch(() => "");
    throw new Error(`OpenRouter endpoints request failed (${response.status}): ${text.slice(0, 200)}`);
  }

  const payload = await response.json() as unknown;
  const record = isRecord(payload) ? payload : {};
  const data = isRecord(record.data) ? record.data : {};
  const endpoints = Array.isArray(data.endpoints)
    ? data.endpoints
    : Array.isArray(record.endpoints)
      ? record.endpoints
      : [];
  return endpoints;
}

function pruneEndpointCache(): void {
  if (endpointCache.size <= endpointCacheMaxEntries) {
    return;
  }
  const overflow = endpointCache.size - endpointCacheMaxEntries;

View on GitHub (pinned to 99f24806c6)

Solutions

  1. Check the embedded status: 401/403 -> fix the API key; 404 -> verify the model id exists; 429 -> back off per the cooldown
  2. Inspect the body snippet in the message for OpenRouter's error detail
  3. Confirm the apiRoot points at the intended OpenRouter deployment

Example fix

// before
apiKey: ""
// after
apiKey: process.env.OPENROUTER_API_KEY
Defensive patterns

Strategy: try-catch

Validate before calling

null

Type guard

const isOpenRouterHttpError = (e: unknown): boolean => e instanceof Error && /OpenRouter endpoints request failed \((\d+)\)/.test(e.message);

Try / catch

try { return await loadModelEndpoints(model); } catch (e) { const m = /request failed \((\d+)/.exec(String((e as Error).message)); if (m) { const status = Number(m[1]); if (status === 401 || status === 403) throw new Error("check OPENROUTER_API_KEY"); if (status === 429) await sleep(cooldown); } throw e; }

Prevention

When it happens

Trigger: HTTP 401/403 (bad API key), 404 (unknown author/slug), 429 (rate limit), or 5xx from OpenRouter.

Common situations: Expired or missing OPENROUTER_API_KEY, removed/deprecated model ids, hitting free-tier rate limits.

Understand the failure class

Background: "API error: {status}" and "HTTP 401/403/404/429/5xx" errors: non-2xx HTTP responses explained — this error's family across 27 libraries.

Related errors


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