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

  1. In the provider dashboard, assign the key a role/scope that includes model-list (read) permission.
  2. Verify the key belongs to the same organization/project as the configured base_url.
  3. If SSO is enforced, complete SSO and regenerate the key.
  4. 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

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

Related errors


AI-assisted analysis of janhq/jan@fad3f12a14 (2026-08-12). Data as JSON: /api/errors/b4a1c0178f7bf245. Report an issue: GitHub.