{"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":"http","errorClass":"Error","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/fad3f12a147d138388a66f0d92a02b2675f65294/web-app/src/services/providers/tauri.ts#L185-L221","documentation":"Thrown by TauriProviderService.fetchModelsFromProvider (providers/tauri.ts:203) when the GET ${base_url}/models request returns 401 after key rotation is exhausted (last key attempt, or status not eligible for further rotation). The provider rejected the API key as missing or invalid. Rotation already attempted all keys before this fires.","triggerScenarios":"The /models endpoint responds 401 on the final key attempt: every key in the keyChain is invalid/revoked, the key field is empty so no auth header was sent, or the provider requires a different auth scheme (e.g. x-goog-api-key but x-api-key was sent).","commonSituations":"API key expired or revoked; key never set (empty); wrong auth header mode for this provider; corporate proxy strips the Authorization header; provider's account is suspended.","solutions":["Re-issue the API key at the provider's dashboard and update it in Settings > Model Providers.","Confirm the key is actually being sent (not empty) and via the header scheme the provider expects.","If behind a proxy, verify it forwards the Authorization / x-api-key header.","Check the provider account is active and the key has model-list scope."],"exampleFix":"// before\nif (response.status === 401) {\n  throw new Error(`Authentication failed: API key is required or invalid for ${provider.provider}`)\n}\n// after: hint at the specific cause when no key was configured at all\nif (response.status === 401) {\n  const hadKey = keyAttempts.some(k => k)\n  throw new Error(hadKey\n    ? `Authentication failed: API key rejected by ${provider.provider}. Re-issue the key.`\n    : `Authentication failed: no API key set for ${provider.provider}. Add one in Settings.`)\n}","handlingStrategy":"try-catch","validationCode":"function hasValidKeyForProvider(p: ModelProvider): boolean {\n  const chain = providerRemoteApiKeyChain(p)\n  return chain.some(k => typeof k === 'string' && k.trim().length > 0)\n}\n// before fetchModelsFromProvider:\nif (!hasValidKeyForProvider(provider)) {\n  throw new Error(`Set an API key for ${provider.provider} in Settings.`)\n}","typeGuard":"function isAuthError(e: unknown, provider: string): boolean {\n  return e instanceof Error && /Authentication failed.*provider/i.test(e.message)\n}","tryCatchPattern":"try {\n  return await providerService.fetchModelsFromProvider(provider)\n} catch (e) {\n  if (e instanceof Error && /Authentication failed/.test(e.message)) {\n    openSettings('model-providers', provider.provider)\n    return []\n  }\n  throw e\n}","preventionTips":["Validate the key is non-empty before the network call.","Confirm the auth header scheme matches what the provider expects.","Surface 're-issue the key' guidance distinctly from network errors.","Strip whitespace from keys on save."],"tags":["provider","auth","api-key","http-status","network","tauri","typescript"],"backgroundTag":null,"analyzedSha":"fad3f12a147d138388a66f0d92a02b2675f65294","analyzedAt":"2026-08-12T20:33:47.516Z","schemaVersion":2},"datasetVersion":"2026-08-12T23:17:12.415Z"}