decolua/9router · error

Kilo API returned ${res.status}

Error message

Kilo API returned ${res.status}

What it means

The kilo free-models route fetches KILO_MODELS_URL with a 10s timeout and expects a 2xx JSON response. If res.ok is false (any 4xx/5xx from the Kilo upstream), the route surfaces the upstream status in this error instead of trying to parse a non-JSON error body.

Source

Thrown at src/app/api/providers/kilo/free-models/route.js:25

let cacheTimestamp = 0;
const CACHE_TTL_MS = 60 * 60 * 1000; // 1 hour

export async function GET() {
  const now = Date.now();

  // Return cached result if still valid
  if (cachedModels && now - cacheTimestamp < CACHE_TTL_MS) {
    return NextResponse.json({ models: cachedModels, cached: true });
  }

  try {
    const res = await fetch(KILO_MODELS_URL, {
      headers: { "Accept": "application/json" },
      signal: AbortSignal.timeout(10000),
    });

    if (!res.ok) {
      throw new Error(`Kilo API returned ${res.status}`);
    }

    const json = await res.json();
    const allModels = json.data || [];

    const freeModels = allModels
      .filter((m) => m.isFree === true)
      .map((m) => ({
        id: m.id,
        name: m.name,
        isFree: true,
        context_length: m.context_length || 0,
      }));

    cachedModels = freeModels;
    cacheTimestamp = now;

    return NextResponse.json({ models: freeModels, cached: false });

View on GitHub (pinned to 90b52e06ff)

Solutions

  1. Retry later if the Kilo API is having an outage (5xx).
  2. Check the returned status in the message: 401/403 means auth/blocking — verify network access to the Kilo endpoint from this machine.
  3. Verify KILO_MODELS_URL is still valid upstream and update the constant if Kilo moved the endpoint.
  4. Reduce polling frequency if hitting 429 rate limits.
Defensive patterns

Strategy: retry

Try / catch

try {
  const models = await fetchFreeModels();
} catch (e) {
  if (e.message.startsWith("Kilo API returned")) {
    const status = parseInt(e.message.match(/\d+$/)?.[0], 10);
    if (status >= 500 || status === 429) await delay(backoff).then(retry);
    else console.error("Kilo upstream rejected the request:", status);
  } else throw e;
}

Prevention

When it happens

Trigger: GET /api/providers/kilo/free-models while the Kilo models API returns 401/403 (auth required), 404 (endpoint moved), 429 (rate limited), or 5xx outage; also when a proxy/firewall intercepts with an error status.

Common situations: Kilo API is down or geo-blocked, the hard-coded KILO_MODELS_URL changed upstream, corporate proxy returns 403, or rate limiting from repeated polling.

Related errors


AI-assisted analysis of decolua/9router@90b52e06ff (2026-08-30). Data as JSON: /api/errors/f0b2a4563e266fb6. Report an issue: GitHub.