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

  1. Add a non-empty key_ids array (<=500 entries) to the request body.
  2. Or set "all_keys_in_team": true when you really mean every active key in the team.
  3. 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

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


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