BerriAI/litellm · error · HTTPException
Key={key.token} has a tpm_limit={key.tpm_limit} which is gre
Error message
Key={key.token} has a tpm_limit={key.tpm_limit} which is greater than the team's tpm_limit={team.tpm_limit}. What it means
LiteLLM enforces that a virtual key's tpm_limit can never exceed the tpm_limit of the team it belongs to (a key is a slice of the team's allowance, not an expansion of it). This check runs on key generation and key update paths for team-scoped keys and returns 403 with the offending key token and both limits. The key token is included in the message, which is a mild information-disclosure consideration in shared logs.
Source
Thrown at litellm/proxy/management_endpoints/key_management_endpoints.py:3312
- The person initiating the change must be either Proxy Admin or Team Admin
"""
# Check if the team has access to the key's models
if len(key.models) > 0:
for model in key.models:
# Skip special sentinel values — "all-team-models" means
# "use whatever the team allows", so it's always valid.
if model == SpecialModelNames.all_team_models.value:
continue
await can_team_access_model(
model=model,
team_object=team,
llm_router=llm_router,
)
# Check if the key's tpm/rpm limit is less than the team's tpm/rpm limit
if key.tpm_limit is not None:
if team.tpm_limit and key.tpm_limit > team.tpm_limit:
raise HTTPException(
status_code=403,
detail=f"Key={key.token} has a tpm_limit={key.tpm_limit} which is greater than the team's tpm_limit={team.tpm_limit}.",
)
if team.rpm_limit and key.rpm_limit and key.rpm_limit > team.rpm_limit:
raise HTTPException(
status_code=403,
detail=f"Key={key.token} has a rpm_limit={key.rpm_limit} which is greater than the team's rpm_limit={team.rpm_limit}.",
)
# Check if the key's user_id is a member of the team
member_object: Final = _get_user_in_team(team_table=cast(LiteLLM_TeamTableCachedObj, team), user_id=key.user_id)
if key.user_id is not None:
if not member_object:
raise HTTPException(
status_code=403,
detail=f"User={key.user_id} is not a member of the team={team.team_id}. Check team members via `/team/info`.",
)
View on GitHub (pinned to 77b7c6c40c)
Solutions
- Raise the team's tpm_limit first (POST /team/update) to at least the desired key limit, then set the key's tpm_limit.
- Or lower the key's tpm_limit to <= the team's tpm_limit.
- Set tpm_limit=null on the key to inherit 'whatever the team allows', which is always valid.
Example fix
# before
client.post("/key/generate", json={"team_id": tid, "tpm_limit": 500000})
# after
client.post("/team/update", json={"team_id": tid, "tpm_limit": 500000})
client.post("/key/generate", json={"team_id": tid, "tpm_limit": 500000}) Defensive patterns
Strategy: validation
Validate before calling
def assert_key_limit_within_team(client, team_id: str, tpm_limit: int | None) -> None:
if tpm_limit is None:
return
team = client.get("/team/info", params={"team_id": team_id}).json()
team_tpm = team.get("tpm_limit")
if team_tpm is not None and tpm_limit > team_tpm:
raise ValueError(f"key tpm_limit {tpm_limit} > team tpm_limit {team_tpm}; raise team limit first") Type guard
def key_tpm_fits_team(key_tpm: int | None, team_tpm: int | None) -> bool:
return key_tpm is None or team_tpm is None or key_tpm <= team_tpm Prevention
- Make 'raise team limit, then key limit' the standard order in every provisioning script.
- Store team limits alongside key limits in your config source so they can't drift apart.
- Prefer leaving key tpm_limit unset to inherit the team's cap.
When it happens
Trigger: POST /key/generate or /key/update with team_id set and tpm_limit greater than that team's tpm_limit (e.g. team tpm_limit=100000, key tpm_limit=500000); bulk team key update that raises tpm_limit on keys of a team whose own limit is lower.
Common situations: Copying key limits from another environment/team without aligning team limits first; raising a team's per-key budgets in config but forgetting to raise the team budget; onboarding scripts that assign a default tpm_limit per key larger than small teams' caps.
Related errors
- Key={key.token} has a rpm_limit={key.rpm_limit} which is gre
- max_budget ({_requested_max_budget}) cannot be set without s
- Maximum {MAX_BATCH_SIZE} keys can be updated at once. Found
- Team {data.team_id} has more than {MAX_BATCH_SIZE} keys. Use
- key_ids must be provided when all_keys_in_team is False
AI-assisted analysis of BerriAI/litellm@77b7c6c40c (2026-08-18).
Data as JSON: /api/errors/e01fdda47dc7dbd6.
Report an issue: GitHub.