{"record":{"id":"885d69eb19c1dbfe","repo":"janhq/jan","slug":"failed-to-fetch-models-from-provider-provider-885d69","errorCode":null,"errorMessage":"Failed to fetch models from ${provider.provider}: ${response.status} ${response.statusText}","messagePattern":"Failed to fetch models from (.+?): (.+?) (.+?)","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"web-app/src/services/providers/tauri.ts","lineNumber":217,"sourceCode":"        }\n\n        if (!response.ok) {\n          if (response.status === 401) {\n            throw new Error(\n              `Authentication failed: API key is required or invalid for ${provider.provider}`\n            )\n          }\n          if (response.status === 403) {\n            throw new Error(\n              `Access forbidden: Check your API key permissions for ${provider.provider}`\n            )\n          }\n          if (response.status === 404) {\n            throw new Error(\n              `Models endpoint not found for ${provider.provider}. Check the base URL configuration.`\n            )\n          }\n          throw new Error(\n            `Failed to fetch models from ${provider.provider}: ${response.status} ${response.statusText}`\n          )\n        }\n\n        const data = await response.json()\n\n        if (data.data && Array.isArray(data.data)) {\n          return data.data\n            .map((model: { id: string }) => model.id)\n            .filter(Boolean)\n        }\n        if (Array.isArray(data)) {\n          return data\n            .filter(Boolean)\n            .map((model) =>\n              typeof model === 'object' && 'id' in model ? model.id : model\n            )\n        }","sourceCodeStart":199,"sourceCodeEnd":235,"githubUrl":"https://github.com/janhq/jan/blob/7205d770c1e097c3daf35a911176410e93bc5564/web-app/src/services/providers/tauri.ts#L199-L235","documentation":"Generic throw for any non-OK response from the provider's /models endpoint that isn't 401, 403, or 404. It reports the raw status code and status text so the developer can diagnose provider-specific failures like 429 rate limiting, 5xx server errors, or 400 bad requests.","triggerScenarios":"GET `${provider.base_url}/models` returned a status other than 401/403/404 (e.g. 429, 500, 502, 400) and no alternative key attempt succeeded.","commonSituations":"Provider rate-limits the account (429); upstream outage or gateway error (5xx); malformed request rejected by an unusual server (400); quota exhausted on a hosted provider.","solutions":["Read the status code in the message: for 429 wait/back off and retry later or check quota.","For 5xx check the provider's status page or restart the local server.","For 400, verify the base URL and headers match the expected API (e.g. Anthropic needs anthropic-version).","Retry the fetch; if persistent, test the endpoint directly with curl to see the response body."],"exampleFix":"// before: hammering a rate-limited endpoint in a loop\nawait fetchModelsFromProvider(provider)\n// after: back off on 429\nif (err.message.includes('429')) await new Promise(r => setTimeout(r, 5000))","handlingStrategy":"retry","validationCode":null,"typeGuard":null,"tryCatchPattern":"try {\n  await fetchModelsFromProvider(provider)\n} catch (e) {\n  const m = e instanceof Error ? e.message : ''\n  if (m.includes('429')) await backoffAndRetry()      // rate limited\n  else if (/5\\d\\d/.test(m)) scheduleRetryLater()       // server error\n  else reportToUser(m)\n}","preventionTips":["Implement exponential backoff for 429/5xx responses.","Monitor provider status pages and quota dashboards.","Cache the model list so transient failures don't block the UI."],"tags":["http-error","network","rate-limit","provider-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"}