BerriAI/litellm · warning · HTTPException
key_ids must be provided when all_keys_in_team is False
Error message
key_ids must be provided when all_keys_in_team is False
What it means
POST /team/key/bulk_update requires exactly one selection mode: either all_keys_in_team=true (update every active key in the team) or an explicit non-empty key_ids list. When all_keys_in_team is false/absent and key_ids is null or empty, there is nothing to update and the endpoint rejects the request with a 400 before touching the database.
Source
Thrown at litellm/proxy/management_endpoints/key_management_endpoints.py:3179
"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)
if h in seen_hashes:
continue
seen_hashes.add(h)
requested_tokens.append(k)
hashed_key_ids.append(h)
existing_keys = await VerificationTokenRepository(prisma_client).table.find_many(
where={"team_id": data.team_id, "token": {"in": hashed_key_ids}}
)
View on GitHub (pinned to 77b7c6c40c)
Solutions
- Add a non-empty key_ids array (<=500 entries) to the request body.
- Or set "all_keys_in_team": true when you really mean every active key in the team.
- Guard your calling code: skip the API call entirely when the computed key list is empty.
Example fix
# before
payload = {"team_id": tid, "update_fields": fields}
if selected_keys:
payload["key_ids"] = selected_keys
client.post("/team/key/bulk_update", json=payload) # fires 400 when selected_keys empty
# after
if not selected_keys:
log.info("no keys selected; skipping bulk update")
else:
client.post("/team/key/bulk_update", json={"team_id": tid, "key_ids": selected_keys, "update_fields": fields}) Defensive patterns
Strategy: validation
Validate before calling
def build_bulk_update_body(team_id: str, key_ids: list[str] | None, all_keys: bool) -> dict:
if all_keys:
return {"team_id": team_id, "all_keys_in_team": True}
if not key_ids:
raise ValueError("key_ids must be a non-empty list when all_keys_in_team is false")
return {"team_id": team_id, "key_ids": key_ids} Type guard
def is_complete_bulk_request(key_ids: list[str] | None, all_keys_in_team: bool | None) -> bool:
return bool(all_keys_in_team) or (key_ids is not None and len(key_ids) > 0) Prevention
- Construct the request body through one validated builder function instead of ad-hoc dicts.
- Skip the call when your selection logic yields zero keys rather than sending an empty payload.
- Cover this in contract tests so a renamed field fails loudly at build time.
When it happens
Trigger: POST /team/key/bulk_update with a body like {"team_id": "my-team"} or {"team_id": "my-team", "key_ids": []} and no all_keys_in_team flag; serializing a request model where key_ids defaulted to an empty list.
Common situations: A generic update helper that builds the payload dynamically and ends up with an empty list (e.g. a filter matched no keys); frontend sending the form before the key selection was populated; copy-pasting the curl example and forgetting the key_ids field.
Understand the failure class
Background: "Missing required field" and "field is required" errors: why libraries reject payloads that omit mandatory fields — this error's family across 20 libraries.
Related errors
- Maximum {MAX_BATCH_SIZE} keys can be updated at once. Found
- Invalid request type
- Malformed request. No keys passed in.
- Team {data.team_id} has more than {MAX_BATCH_SIZE} keys. Use
- No keys found for team {data.team_id}
AI-assisted analysis of BerriAI/litellm@77b7c6c40c (2026-08-18).
Data as JSON: /api/errors/81c4121ecd5d9bc2.
Report an issue: GitHub.