BerriAI/litellm · warning · HTTPException

Team {data.team_id} has more than {MAX_BATCH_SIZE} keys. Use

Error message

Team {data.team_id} has more than {MAX_BATCH_SIZE} keys. Use `key_ids` to update in batches of {MAX_BATCH_SIZE}.

What it means

On POST /team/key/bulk_update with all_keys_in_team=true, LiteLLM fetches the team's active keys (not blocked, not expired) with take=MAX_BATCH_SIZE+1. If it gets back more than 500 rows it aborts with this 400 rather than silently updating only the first 500. It is a completeness guard: the 'all keys' mode is only allowed when it can actually mean all keys.

Source

Thrown at litellm/proxy/management_endpoints/key_management_endpoints.py:3170

    if data.all_keys_in_team:
        # "all" excludes blocked/expired — bulk refresh shouldn't revive a key an admin disabled.
        # `blocked` is Boolean? with no default; `/key/generate` writes NULL. Prisma's `NOT`
        # excludes NULLs, so explicitly OR `false` with `null` to include them.
        now: Final = datetime.now(timezone.utc)
        existing_keys = await VerificationTokenRepository(prisma_client).table.find_many(
            where={
                "team_id": data.team_id,
                "AND": [
                    {"OR": [{"blocked": False}, {"blocked": None}]},
                    {"OR": [{"expires": None}, {"expires": {"gt": now}}]},
                ],
            },
            order={"token": "asc"},
            take=MAX_BATCH_SIZE + 1,
        )
        if len(existing_keys) > MAX_BATCH_SIZE:
            raise HTTPException(
                status_code=400,
                detail={
                    "error": f"Team {data.team_id} has more than {MAX_BATCH_SIZE} keys. Use `key_ids` to update in batches of {MAX_BATCH_SIZE}."
                },
            )
        requested_tokens = [row.token for row in existing_keys]
    else:
        if data.key_ids is None or len(data.key_ids) == 0:
            raise HTTPException(
                status_code=400,
                detail={"error": "key_ids must be provided when all_keys_in_team is False"},
            )
        # Dedupe by hashed form — duplicates collapse to one update.
        requested_tokens = []
        hashed_key_ids: Final = []
        seen_hashes: Final = set()
        for k in data.key_ids:
            h = _hash_token_if_needed(k)

View on GitHub (pinned to 77b7c6c40c)

Solutions

  1. Switch to the key_ids mode: query the team's key tokens (e.g. GET /team/info with expand keys, or /key/info batch) and then POST them in chunks of <=500 with all_keys_in_team omitted/false.
  2. If most keys are stale, clean up blocked/expired keys first — they are excluded from the 500 count, so pruning may drop the team under the limit.
  3. Split very large teams into multiple smaller teams if bulk operations are a regular workflow.

Example fix

# before
client.post("/team/key/bulk_update", json={"team_id": tid, "all_keys_in_team": True, "update_fields": {...}})

# after
keys = get_all_team_key_ids(tid)  # via /team/info or /v2/key/info
for i in range(0, len(keys), 500):
    client.post("/team/key/bulk_update", json={
        "team_id": tid,
        "key_ids": keys[i:i+500],
        "update_fields": {...},
    })
Defensive patterns

Strategy: validation

Validate before calling

# Before using all_keys_in_team, check the team's active key count
info = client.get("/team/info", params={"team_id": tid}).json()
active_keys = count_active_team_keys(info)  # exclude blocked/expired
if active_keys > 500:
    key_ids = fetch_team_key_ids(tid)  # then chunk these

Type guard

def can_use_all_keys_mode(active_key_count: int) -> bool:
    return active_key_count <= 500

Try / catch

try:
    resp = client.post("/team/key/bulk_update", json={"team_id": tid, "all_keys_in_team": True, ...})
    resp.raise_for_status()
except HTTPError as e:
    if e.response.status_code == 400 and "more than" in e.response.text:
        switch_to_chunked_key_ids_mode(tid)

Prevention

When it happens

Trigger: POST /team/key/bulk_update with {"team_id": ..., "all_keys_in_team": true} on a team that has 501 or more active (unblocked, unexpired) keys.

Common situations: Bulk-rotating budgets or metadata on a large organization-wide team; teams grown past 500 keys through automated key issuance; a 'rotate all team keys' admin script.

Related errors


AI-assisted analysis of BerriAI/litellm@77b7c6c40c (2026-08-18). Data as JSON: /api/errors/28997a3f2ba3a75a. Report an issue: GitHub.