janhq/jan · error

Failed to fetch models from

Error message

Failed to fetch models from ${provider.provider}: ${lastStatus} ${lastStatusText}

What it means

fetchTopRemoteModels iterates remote provider catalog endpoints; if every attempted endpoint returns a non-OK HTTP status, it throws with the last response's status code and status text. It signals that the provider's model catalog API was reachable but rejected the request.

Solutions

  1. Check the provider API key in provider settings and re-authenticate
  2. Verify the provider base_url points at the correct API host
  3. Call the provider's /models endpoint with curl to confirm access
  4. Check network/proxy configuration that could alter responses

Example fix

// before
throw new Error(`Failed to fetch models from ${provider.provider}: ${lastStatus} ${lastStatusText}`)
// after
// inspect lastStatus first; e.g. 401 => refresh the API key before retrying
if (lastStatus === 401) throw new Error(`Invalid API key for ${provider.provider}`)
throw new Error(`Failed to fetch models from ${provider.provider}: ${lastStatus} ${lastStatusText}`)
Defensive patterns

Strategy: retry

Validate before calling

const res = await fetch(url, { headers })
if (!res.ok) throw new Error(`${res.status} ${res.statusText}`)

Type guard

function isOk(r: Response): boolean { return r.ok }

Try / catch

try { const models = await fetchTopRemoteModels() } catch (e) { if (String(e).includes('401')) refreshToken(); else showCatalogError(e) }

Prevention

When it happens

Trigger: fetchTopRemoteModels called when a provider endpoint (e.g. OpenAI, Groq) returns 401/403/404/5xx on its /models route for all attempted URLs.

Common situations: Expired or missing API key on the remote provider, wrong base_url in provider settings, provider blocking the /models endpoint, or a proxy/firewall returning an error page.

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 janhq/jan@7205d770c1 (2026-09-17). Data as JSON: /api/errors/8202175c729cf704. Report an issue: GitHub.

Appendix: source

Thrown at web-app/src/lib/remoteModelCatalog.ts:231

  for (let i = 0; i < attempts.length; i++) {
    const result = await getJson(
      fetchImpl,
      `${provider.base_url}/models`,
      buildHeaders(provider, attempts[i])
    )
    lastStatus = result.status
    lastStatusText = result.statusText
    if (!result.ok) {
      if ([401, 403, 429].includes(result.status) && i < attempts.length - 1) continue
      throw new Error(`Failed to fetch models from ${provider.provider}: ${result.status} ${result.statusText}`)
    }

    const body = result.body as { data?: unknown }
    const rows = Array.isArray(body?.data) ? (body.data as unknown[]) : []
    return normalizeCatalog(kind, rows)
  }

  throw new Error(`Failed to fetch models from ${provider.provider}: ${lastStatus} ${lastStatusText}`)
}

function normalizeCatalog(kind: CatalogKind, rows: unknown[]): RemoteCatalogModel[] {
  const inferCaps =
    kind === 'openai'
      ? inferOpenAICapabilities
      : kind === 'gemini'
        ? inferGeminiCapabilities
        : inferAnthropicCapabilities

  const parsed: RemoteCatalogModel[] = []
  for (const raw of rows) {
    if (!raw || typeof raw !== 'object') continue
    const row = raw as Record<string, unknown>
    const id = typeof row.id === 'string' ? row.id : null
    if (!id) continue
    const caps = inferCaps(id)
    if (!caps) continue

View on GitHub (pinned to 7205d770c1)