{"record":{"id":"718fc16f1fe48e05","repo":"janhq/jan","slug":"authentication-failed-api-key-is-required-or-inva","errorCode":null,"errorMessage":"Authentication failed: API key is required or invalid for ${provider.provider}","messagePattern":"Authentication failed: API key is required or invalid for (.+?)","errorType":"exception","errorClass":null,"httpStatus":401,"severity":"error","filePath":"web-app/src/services/providers/tauri.ts","lineNumber":203,"sourceCode":"\n        const response = await fetchTauri(`${provider.base_url}/models`, {\n          method: 'GET',\n          headers,\n        })\n\n        lastStatus = response.status\n        lastStatusText = response.statusText\n\n        if (\n          [401, 403, 429].includes(response.status) &&\n          ki < keyAttempts.length - 1\n        ) {\n          continue\n        }\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","sourceCodeStart":185,"sourceCodeEnd":221,"githubUrl":"https://github.com/janhq/jan/blob/7205d770c1e097c3daf35a911176410e93bc5564/web-app/src/services/providers/tauri.ts#L185-L221","documentation":"fetchModelsFromProvider throws this when the provider's /models endpoint responds with HTTP 401. It means the API key sent (via x-api-key / Authorization: Bearer headers) is missing, empty, expired, or rejected by the provider. The code tries each configured key attempt on 401/403/429 before giving up with this error.","triggerScenarios":"GET `${provider.base_url}/models` returned 401 after exhausting all keyAttempts; happens when no API key is configured for a hosted provider, or the configured key is invalid/expired/revoked.","commonSituations":"Using Jan with OpenAI/Anthropic without pasting an API key in settings; key rotated or revoked upstream; wrong provider selected so the key is sent to a different vendor; trailing whitespace or placeholder key ('sk-...') saved in settings; self-hosted server requiring auth the app doesn't know about.","solutions":["Open provider settings and enter a valid API key for the selected provider (it is stored in the OS keyring).","Verify the key works with a direct curl call to the provider's /models endpoint.","If using a self-hosted/proxy endpoint that needs no auth, confirm the provider type matches the endpoint so keys/headers are sent correctly.","Regenerate the key on the provider dashboard if it was rotated or revoked."],"exampleFix":"// before: provider saved without a key\n{ provider: 'openai', base_url: 'https://api.openai.com/v1', api_key: '' }\n// after\n{ provider: 'openai', base_url: 'https://api.openai.com/v1', api_key: 'sk-<valid-key>' }","handlingStrategy":"validation","validationCode":"if (!provider.api_key || provider.api_key.trim() === '' || provider.api_key.startsWith('sk-...')) {\n  throw new Error(`Configure a valid API key for ${provider.provider} before fetching models`)\n}","typeGuard":"function hasApiKey(p: { api_key?: string | null }): p is typeof p & { api_key: string } {\n  return typeof p.api_key === 'string' && p.api_key.trim().length > 0\n}","tryCatchPattern":"try {\n  await fetchModelsFromProvider(provider)\n} catch (e) {\n  if (e instanceof Error && e.message.startsWith('Authentication failed')) {\n    openProviderSettings(provider.provider) // prompt user to fix the key\n  }\n}","preventionTips":["Validate that an API key exists in settings before calling model-listing APIs for hosted providers.","Test keys with a direct curl call when configuring a provider.","Rotate keys proactively and re-enter them after revocation.","Match provider type to endpoint so keys are sent to the right vendor."],"tags":["http-401","api-key","authentication","network"],"backgroundTag":"authentication-required","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"}