janhq/jan · error
Access forbidden: Check your API key permissions for
Error message
Access forbidden: Check your API key permissions for ${provider.provider} What it means
Thrown when the provider's /models endpoint responds with HTTP 403. The request was authenticated (or at least not rejected as unauthenticated) but the key or origin lacks permission for this resource, or the server is blocking access (e.g. CORS/origin policy, region block, plan restrictions).
Solutions
- Check the API key's permissions/scopes on the provider dashboard and grant model listing access.
- Verify the base URL points to the correct provider API and that your plan/region allows it.
- For self-hosted servers, allow the tauri://localhost origin or configure CORS/ACL rules.
- Try a different (unrestricted) API key via curl to isolate key vs. network blocking.
Example fix
// before: restricted key without read scope headers['Authorization'] = 'Bearer sk-restricted-no-scope' // after: use a key with models:list permission headers['Authorization'] = 'Bearer sk-<key-with-models-read>'
Defensive patterns
Strategy: try-catch
Validate before calling
// Verify key permissions out-of-band before calling:
const res = await fetch(`${provider.base_url}/models`, { headers: { Authorization: `Bearer ${key}` } })
if (res.status === 403) console.warn('Key lacks models:list permission') Try / catch
try {
await fetchModelsFromProvider(provider)
} catch (e) {
if (e instanceof Error && e.message.startsWith('Access forbidden')) {
showPermissionHelp(provider.provider) // guide user to key scopes/CORS
}
} Prevention
- Use API keys with the least scopes that still include model listing.
- When proxying, allow the app's origin (tauri://localhost) in CORS/ACL rules.
- Check plan/region restrictions on the provider dashboard before onboarding.
When it happens
Trigger: GET `${provider.base_url}/models` returned 403 after all key attempts; typical when the key is valid but scoped without models:list permission, or the remote endpoint rejects the tauri://localhost origin.
Common situations: Restricted/scoped API key without model-list permission; provider blocks requests from browser/webview origins (CORS); organization policy or paid-plan gating; proxy/firewall returning 403; wrong base_url pointing at a service with different ACLs.
Understand the failure class
Background: Permission denied / not authorized / 403 Forbidden: access-control rejections when the caller lacks the required role, grant, or ownership — this error's family across 18 libraries.
- Authentication and authorization failures — expired tokens, bad credentials, and missing scopes.
Related errors
- API key rotation exhausted
- Authentication failed: API key is required or invalid for
- Failed to fetch models from
- Failed to save store
- No API key configured for
AI-assisted analysis of janhq/jan@7205d770c1 (2026-09-17).
Data as JSON: /api/errors/b4a1c0178f7bf245.
Report an issue: GitHub.
Appendix: source
Thrown at web-app/src/services/providers/tauri.ts:208
lastStatus = response.status
lastStatusText = response.statusText
if (
[401, 403, 429].includes(response.status) &&
ki < keyAttempts.length - 1
) {
continue
}
if (!response.ok) {
if (response.status === 401) {
throw new Error(
`Authentication failed: API key is required or invalid for ${provider.provider}`
)
}
if (response.status === 403) {
throw new Error(
`Access forbidden: Check your API key permissions for ${provider.provider}`
)
}
if (response.status === 404) {
throw new Error(
`Models endpoint not found for ${provider.provider}. Check the base URL configuration.`
)
}
throw new Error(
`Failed to fetch models from ${provider.provider}: ${response.status} ${response.statusText}`
)
}
const data = await response.json()
if (data.data && Array.isArray(data.data)) {
return data.data
.map((model: { id: string }) => model.id)View on GitHub (pinned to 7205d770c1)