BerriAI/litellm · warning · ValueError

Invalid request type

Error message

Invalid request type

What it means

POST /key/delete dispatches on which field of the KeyRequest body is populated: data.keys triggers token deletion, data.key_aliases triggers alias deletion. If both are falsy the handler raises this ValueError ('Invalid request type'), which the endpoint wrapper converts into an error response. In other words: the delete request carried neither keys nor key_aliases.

Source

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

                tokens=data.keys,
                user_api_key_cache=user_api_key_cache,
                user_api_key_dict=user_api_key_dict,
                litellm_changed_by=litellm_changed_by,
            )
            num_keys_to_be_deleted = len(data.keys)
            deleted_keys = data.keys
        elif data.key_aliases:
            number_deleted_keys, _keys_being_deleted = await delete_key_aliases(
                key_aliases=data.key_aliases,
                prisma_client=prisma_client,
                user_api_key_cache=user_api_key_cache,
                user_api_key_dict=user_api_key_dict,
                litellm_changed_by=litellm_changed_by,
            )
            num_keys_to_be_deleted = len(data.key_aliases)
            deleted_keys = data.key_aliases
        else:
            raise ValueError("Invalid request type")

        if number_deleted_keys is None:
            raise ProxyException(
                message="Failed to delete keys got None response from delete_verification_token",
                type=ProxyErrorTypes.internal_server_error,
                param="keys",
                code=status.HTTP_500_INTERNAL_SERVER_ERROR,
            )
        verbose_proxy_logger.debug("/key/delete - deleted_keys=%s", number_deleted_keys)

        try:
            assert num_keys_to_be_deleted == len(deleted_keys)
        except Exception:
            raise HTTPException(
                status_code=400,
                detail={
                    "error": f"Not all keys passed in were deleted. This probably means you don't have access to delete all the keys passed in. Keys passed in={num_keys_to_be_deleted}, Deleted keys ={number_deleted_keys}"
                },

View on GitHub (pinned to 77b7c6c40c)

Solutions

  1. Send {"keys": ["sk-..."]} (list of key tokens) to delete by token, or {"key_aliases": ["alias1"]} to delete by alias.
  2. Check for typos in the field name — only `keys` and `key_aliases` are recognized.
  3. Skip the API call when your computed delete list is empty.

Example fix

# before
client.post("/key/delete", json={"key": key_to_delete})

# after
client.post("/key/delete", json={"keys": [key_to_delete]})
Defensive patterns

Strategy: validation

Validate before calling

def build_delete_body(keys: list[str] | None = None, key_aliases: list[str] | None = None) -> dict:
    if keys:
        return {"keys": keys}
    if key_aliases:
        return {"key_aliases": key_aliases}
    raise ValueError("/key/delete requires non-empty 'keys' or 'key_aliases'")

Type guard

def is_valid_delete_request(keys: list[str] | None, key_aliases: list[str] | None) -> bool:
    return bool(keys) or bool(key_aliases)

Prevention

When it happens

Trigger: POST /key/delete with an empty body, {}, {"keys": []} and no aliases, or a payload using a wrong field name (e.g. {"key": "sk-..."} singular, or key_ids).

Common situations: Client code building the JSON dynamically and emitting {} when nothing to delete; field-name drift after upgrading from an older/newer API that used a different property; manual curl missing the -d body.

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/27ea5fa0e92840d1. Report an issue: GitHub.