BerriAI/litellm · error · Exception
Unmapped scope type - {type(token['scope'])}. Supported type
Error message
Unmapped scope type - {type(token['scope'])}. Supported types - list, str. What it means
Raised in JWTAuthManager.get_scopes (litellm/proxy/auth/handle_jwt.py) while extracting the scope claim from a decoded JWT. LiteLLM accepts scope as either a space-separated string (the OAuth standard) or a list of strings; any other JSON type (number, object, boolean, null-as-present) hits the else branch and raises this generic Exception, failing authentication.
Source
Thrown at litellm/proxy/auth/handle_jwt.py:599
key_path=self.litellm_jwtauth.org_alias_jwt_field,
default=default_value,
)
return org_alias
else:
org_alias = None
except KeyError:
org_alias = default_value
return org_alias
def get_scopes(self, token: dict) -> list[str]:
try:
if isinstance(token["scope"], str):
# Assuming the scopes are stored in 'scope' claim and are space-separated
scopes = token["scope"].split()
elif isinstance(token["scope"], list):
scopes = token["scope"]
else:
raise Exception(f"Unmapped scope type - {type(token['scope'])}. Supported types - list, str.")
except KeyError:
scopes = []
return scopes
async def _resolve_jwks_url(self, url: str) -> str:
"""
If url points to an OIDC discovery document (*.well-known/openid-configuration),
fetch it and return the jwks_uri contained within. Otherwise return url unchanged.
This lets JWT_PUBLIC_KEY_URL be set to a well-known discovery endpoint instead of
requiring operators to manually find the JWKS URL.
"""
if ".well-known/openid-configuration" not in url:
return url
cache_key: Final = f"litellm_oidc_discovery_{url}"
cached_jwks_uri: Final = await self.user_api_key_cache.async_get_cache(cache_key)
if cached_jwks_uri is not None:
return cached_jwks_uriView on GitHub (pinned to 77b7c6c40c)
Solutions
- Fix the token issuer so the scope claim is a space-separated string ("read write") or an array of strings (["read", "write"])
- Decode the incoming token (e.g. at jwt.io) and inspect the scope claim's JSON type to confirm the mismatch
- If you control neither side, mint the scope correctly in a pre-auth step or ask the IdP admin to fix the claim mapping
Example fix
// before: token payload with unmapped scope type
{ "sub": "user", "scope": { "models": "read" } }
// after: standard space-separated string (or array)
{ "sub": "user", "scope": "models:read chat:completion" } Defensive patterns
Strategy: type-guard
Validate before calling
import jwt as pyjwt
def token_scope_is_supported(token: str) -> bool:
payload = pyjwt.decode(token, options={"verify_signature": False})
scope = payload.get("scope")
return scope is None or isinstance(scope, (str, list)) Type guard
from typing import Union
def is_supported_scope(scope: object) -> bool:
"""LiteLLM accepts space-separated str or list[str]; anything else raises at auth time."""
if isinstance(scope, str):
return len(scope.split()) > 0 or scope == ""
if isinstance(scope, list):
return all(isinstance(s, str) for s in scope)
return False Prevention
- When minting custom JWTs, emit scope as a space-separated string per OAuth convention
- Add claim-type assertions to your token-minting test suite (scope is str or list of str)
- Validate third-party IdP claim mappings before switching a realm to JWT auth on the proxy
When it happens
Trigger: A request authenticated with a JWT whose scope claim is neither a string nor a list - for example {"scope": 123}, {"scope": {"read": true}}, or {"scope": true} - and the proxy config uses scope-based auth (e.g. scope_endpoints, scope mappings).
Common situations: A custom/internal token minter that encodes scopes as a JSON object or integer; a misconfigured IdP custom claim rule; testing with hand-crafted tokens where scope was written as a non-standard type.
Related errors
- JWT Auth: OIDC discovery endpoint {url} returned status {res
- JWT Auth: Failed to parse OIDC discovery document at {url}:
- JWT Auth: OIDC discovery document at {url} does not contain
- Error parsing response: {e}. Check server logs for original
- No matching public key found. keys={resolved_jwks_url}, kid=
AI-assisted analysis of BerriAI/litellm@77b7c6c40c (2026-08-18).
Data as JSON: /api/errors/54a0a5079ab24584.
Report an issue: GitHub.