BerriAI/litellm · error · Exception
No team found in token. Checked team_id field '{team_id_fiel
Error message
No team found in token. Checked team_id field '{team_id_field}' and team_alias field '{team_alias_field}'.{hint} What it means
JWT auth tried to resolve a team from the token using `team_id_jwt_field` (and `team_alias_jwt_field`) and found nothing usable in either. The trailing hint (when present) explains a known pitfall: get_nested_value does not support dot-index ('roles.0') or bracket ('roles[0]') access — if the claim is a list, configure the bare field name and LiteLLM takes the first element.
Source
Thrown at litellm/proxy/auth/handle_jwt.py:1285
parts: Final = team_id_field.rsplit(".", 1)
if parts[-1].isdigit():
base_field = parts[0]
hint = (
f" Hint: dot-notation array indexing (e.g. '{team_id_field}') is not "
f"supported. Use '{base_field}' instead — LiteLLM automatically "
f"uses the first element when the field value is a list."
)
# "roles[0]" — bracket-notation indexing is also not supported in get_nested_value
elif "[" in team_id_field and team_id_field.endswith("]"):
m: Final = re.match(r"^(\w+)\[(\d+)\]$", team_id_field)
if m:
base_field = m.group(1)
hint = (
f" Hint: array indexing (e.g. '{team_id_field}') is not supported "
f"in team_id_jwt_field. Use '{base_field}' instead — LiteLLM "
f"automatically uses the first element when the field value is a list."
)
raise Exception(
f"No team found in token. Checked team_id field '{team_id_field}' and team_alias field '{team_alias_field}'.{hint}"
)
return individual_team_id, team_object
@staticmethod
def get_all_team_ids(jwt_handler: JWTHandler, jwt_valid_token: dict) -> set[str]:
"""Get combined team IDs from groups and individual team_id"""
team_ids_from_groups: Final = jwt_handler.get_team_ids_from_jwt(token=jwt_valid_token)
all_team_ids: Final = set(team_ids_from_groups)
return all_team_ids
@staticmethod
def _team_has_passthrough_route_access(
team_object: LiteLLM_TeamTable | None,
route: str,View on GitHub (pinned to 77b7c6c40c)
Solutions
- Decode the JWT and find the actual claim holding the team/group id; set `team_id_jwt_field` to that exact name (dot-paths like 'tenant.team_id' are supported).
- If the claim is a list (e.g. Azure 'roles'), set the bare field name ('roles') — LiteLLM uses the first element; do NOT use 'roles[0]' or 'roles.0'.
- If the token simply has no team claim, either remove team_id_jwt_field, use `team_id_default`, or enable fallback mechanisms.
- For alias-based lookup, verify `team_alias_jwt_field` matches the claim carrying the team alias in the DB.
Example fix
# config.yaml — before (Azure AD token with roles: ["team-123"]) litellm_jwtauth: team_id_jwt_field: "roles[0]" # after litellm_jwtauth: team_id_jwt_field: "roles"
Defensive patterns
Strategy: validation
Validate before calling
claims = jwt_claims(token)
field = CONFIG['litellm_jwtauth']['team_id_jwt_field']
val = claims.get(field) if '.' not in field else nested_get(claims, field)
if val is None or val == []:
raise ValueError(f'token lacks team claim {field!r}; fix team_id_jwt_field or IdP token')
if isinstance(val, list) and not val:
raise ValueError('team claim is an empty list') Type guard
def has_team_claim(claims: dict, field: str) -> bool:
v = claims
for part in field.split('.'):
if not isinstance(v, dict) or part not in v:
return False
v = v[part]
return bool(v) or isinstance(v, list) and len(v) > 0 Try / catch
try:
team_id, team_obj = JWTAuthManager.get_team_object(claims, ...)
except Exception as e:
if 'No team found in token' in str(e):
# hint in message explains list/bracket pitfalls — surface it to the operator
raise ConfigError(str(e)) from e
raise Prevention
- Never use bracket or dot-index notation ('roles[0]', 'roles.0') in team_id_jwt_field; use the bare list field.
- Assert the configured field exists in a decoded sample token in integration tests.
- Keep a matrix of IdP -> team claim name in the deployment docs.
When it happens
Trigger: `team_id_jwt_field` set to a claim that doesn't exist in the token (e.g. 'client_id' for Azure AD tokens that use 'roles' or 'tid'). Field configured as 'roles[0]' or 'groups.0'. Claim exists but is null/empty. Nested path like 'tenant.team_id' where the parent key differs.
Common situations: Switching IdPs (Okta -> Azure AD) without updating team_id_jwt_field. Azure AD tokens where team info lives in the array-valued 'roles' or 'groups' claim — developers naturally write 'roles[0]' which is unsupported. Testing with tokens generated by jwt.io without the expected claims.
Related errors
- You must be a LiteLLM Enterprise user to use this feature. I
- custom_ui_sso_sign_in_handler is not configured. Please set
- 🚨🚨🚨 DISABLING LLM API ENDPOINTS is an Enterprise feature
- 🚨🚨🚨 DISABLING ADMIN ENDPOINTS is an Enterprise feature 🚨
- Invalid mode: {custom_auth_settings['mode']}
AI-assisted analysis of BerriAI/litellm@77b7c6c40c (2026-08-18).
Data as JSON: /api/errors/66bd8e0ea1072e23.
Report an issue: GitHub.