janhq/jan · error · Error
Access forbidden: Check your API key permissions for ${provi
Error message
Access forbidden: Check your API key permissions for ${provider.provider} What it means
Thrown by TauriProviderService.fetchModelsFromProvider (providers/tauri.ts:208) when the GET ${base_url}/models request returns 403 after key rotation is exhausted. Unlike 401 (key missing/invalid), 403 means the key authenticated but lacks permission to list models for this account/workspace.
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 fad3f12a14)
Solutions
- In the provider dashboard, assign the key a role/scope that includes model-list (read) permission.
- Verify the key belongs to the same organization/project as the configured base_url.
- If SSO is enforced, complete SSO and regenerate the key.
- Switch to an account/plan that permits listing models.
Example fix
// before
if (response.status === 403) {
throw new Error(`Access forbidden: Check your API key permissions for ${provider.provider}`)
}
// after: keep the message but also surface the upstream body if present
if (response.status === 403) {
const detail = await safeReadError(response)
throw new Error(`Access forbidden for ${provider.provider}: ${detail ?? 'key lacks model-list scope'}`)
} Defensive patterns
Strategy: try-catch
Validate before calling
function keyHasReadScope(scopes: string[]): boolean {
return scopes.some(s => /model|read|catalog/i.test(s))
}
// when the provider exposes key scopes, validate before the request Type guard
function isForbiddenError(e: unknown, provider: string): boolean {
return e instanceof Error && /Access forbidden.*provider/i.test(e.message)
} Try / catch
try {
return await providerService.fetchModelsFromProvider(provider)
} catch (e) {
if (e instanceof Error && /Access forbidden/.test(e.message)) {
toast.error(`The key for ${provider.provider} lacks model-list permission. Use a broader-scoped key.`)
return []
}
throw e
} Prevention
- Use a key whose scope includes model-list/read, not inference-only.
- Verify the key belongs to the same org/project as the base_url.
- Complete SSO if the provider enforces it before issuing keys.
- Distinguish 403 (permissions) from 401 (auth) in user messaging.
When it happens
Trigger: The API key is valid (passed auth) but the associated account/role is not permitted to call /models: restricted scope, read-only key without model-list permission, organization SSO required, or plan tier restriction.
Common situations: Key created with narrow scope (inference-only, no catalog read); enterprise provider requiring an admin-granted role; trial account without model-list access; key belongs to a different org/project than the base_url.
Understand the failure class
- Authentication and authorization failures — expired tokens, bad credentials, and missing scopes.
Related errors
- Authentication failed: API key is required or invalid for ${
- Models endpoint not found for ${provider.provider}. Check th
- Failed to fetch models from ${provider.provider}: ${result.s
- Failed to fetch HuggingFace repository: ${response.status} $
- Provider must have base_url configured
AI-assisted analysis of janhq/jan@fad3f12a14 (2026-08-12).
Data as JSON: /api/errors/b4a1c0178f7bf245.
Report an issue: GitHub.