{"record":{"id":"8202175c729cf704","repo":"janhq/jan","slug":"failed-to-fetch-models-from-provider-provider-820217","errorCode":null,"errorMessage":"Failed to fetch models from ${provider.provider}: ${lastStatus} ${lastStatusText}","messagePattern":"Failed to fetch models from (.+?): (.+?) (.+?)","errorType":"http","errorClass":null,"httpStatus":null,"severity":"error","filePath":"web-app/src/lib/remoteModelCatalog.ts","lineNumber":231,"sourceCode":"  for (let i = 0; i < attempts.length; i++) {\n    const result = await getJson(\n      fetchImpl,\n      `${provider.base_url}/models`,\n      buildHeaders(provider, attempts[i])\n    )\n    lastStatus = result.status\n    lastStatusText = result.statusText\n    if (!result.ok) {\n      if ([401, 403, 429].includes(result.status) && i < attempts.length - 1) continue\n      throw new Error(`Failed to fetch models from ${provider.provider}: ${result.status} ${result.statusText}`)\n    }\n\n    const body = result.body as { data?: unknown }\n    const rows = Array.isArray(body?.data) ? (body.data as unknown[]) : []\n    return normalizeCatalog(kind, rows)\n  }\n\n  throw new Error(`Failed to fetch models from ${provider.provider}: ${lastStatus} ${lastStatusText}`)\n}\n\nfunction normalizeCatalog(kind: CatalogKind, rows: unknown[]): RemoteCatalogModel[] {\n  const inferCaps =\n    kind === 'openai'\n      ? inferOpenAICapabilities\n      : kind === 'gemini'\n        ? inferGeminiCapabilities\n        : inferAnthropicCapabilities\n\n  const parsed: RemoteCatalogModel[] = []\n  for (const raw of rows) {\n    if (!raw || typeof raw !== 'object') continue\n    const row = raw as Record<string, unknown>\n    const id = typeof row.id === 'string' ? row.id : null\n    if (!id) continue\n    const caps = inferCaps(id)\n    if (!caps) continue","sourceCodeStart":213,"sourceCodeEnd":249,"githubUrl":"https://github.com/janhq/jan/blob/7205d770c1e097c3daf35a911176410e93bc5564/web-app/src/lib/remoteModelCatalog.ts#L213-L249","documentation":"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.","triggerScenarios":"fetchTopRemoteModels called when a provider endpoint (e.g. OpenAI, Groq) returns 401/403/404/5xx on its /models route for all attempted URLs.","commonSituations":"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.","solutions":["Check the provider API key in provider settings and re-authenticate","Verify the provider base_url points at the correct API host","Call the provider's /models endpoint with curl to confirm access","Check network/proxy configuration that could alter responses"],"exampleFix":"// before\nthrow new Error(`Failed to fetch models from ${provider.provider}: ${lastStatus} ${lastStatusText}`)\n// after\n// inspect lastStatus first; e.g. 401 => refresh the API key before retrying\nif (lastStatus === 401) throw new Error(`Invalid API key for ${provider.provider}`)\nthrow new Error(`Failed to fetch models from ${provider.provider}: ${lastStatus} ${lastStatusText}`)","handlingStrategy":"retry","validationCode":"const res = await fetch(url, { headers })\nif (!res.ok) throw new Error(`${res.status} ${res.statusText}`)","typeGuard":"function isOk(r: Response): boolean { return r.ok }","tryCatchPattern":"try { const models = await fetchTopRemoteModels() } catch (e) { if (String(e).includes('401')) refreshToken(); else showCatalogError(e) }","preventionTips":["Store and refresh provider API keys proactively","Test provider endpoints with curl before wiring them in","Surface HTTP status to the user instead of failing silently"],"tags":["network","http","api"],"backgroundTag":"http-error-response","analyzedSha":"7205d770c1e097c3daf35a911176410e93bc5564","analyzedAt":"2026-09-17T14:27:30.100Z","contentChangedAt":"2026-09-17T14:27:30.100Z","schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}