BerriAI/litellm · error · HTTPException

Only proxy admins can enable throttle_on_budget_exceeded on

Error message

Only proxy admins can enable throttle_on_budget_exceeded on a key.

What it means

LiteLLM Proxy rejects key creation/update when the request body sets throttle_on_budget_exceeded=true but the authenticated caller is not a proxy admin (user_role != PROXY_ADMIN). This flag throttles (instead of blocks) a key once its budget is exceeded, an admin-only control. The check runs in _common_key_generation_helper, so it applies to both /key/generate and /key/update.

Source

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

) -> GenerateKeyResponse:
    from litellm.proxy.proxy_server import (
        litellm_proxy_admin_name,
        llm_router,
        premium_user,
        prisma_client,
    )

    common_key_access_checks(
        user_api_key_dict=user_api_key_dict,
        data=data,
        llm_router=llm_router,
        premium_user=premium_user,
    )

    validate_budget_duration(data.budget_duration)

    if data.throttle_on_budget_exceeded is True and user_api_key_dict.user_role != LitellmUserRoles.PROXY_ADMIN.value:
        raise HTTPException(
            status_code=403,
            detail={"error": "Only proxy admins can enable throttle_on_budget_exceeded on a key."},
        )

    enforce_output_token_estimates_are_admin_only(
        data=data,
        existing_metadata=None,
        user_api_key_dict=user_api_key_dict,
        entity="key",
    )

    if data.metadata is not None and data.metadata.get("service_account_id") is not None and data.team_id is None:
        await validate_team_id_used_in_service_account_request(
            team_id=data.team_id,
            prisma_client=prisma_client,
        )

    # Capture caller-supplied max_budget and team_id before any defaults or

View on GitHub (pinned to 77b7c6c40c)

Solutions

  1. Remove throttle_on_budget_exceeded from the request body if you do not need it
  2. Re-send the same request with a proxy admin virtual key (a key issued to the admin user, role proxy_admin)
  3. Have a proxy admin create/update the key on behalf of the non-admin caller

Example fix

// before (caller is a team admin key)
curl -X POST http://localhost:4000/key/generate \
  -H "Authorization: Bearer sk-team-admin-key" \
  -d '{"max_budget": 5, "throttle_on_budget_exceeded": true}'

// after (use the proxy admin key for this flag)
curl -X POST http://localhost:4000/key/generate \
  -H "Authorization: Bearer sk-proxy-admin-key" \
  -d '{"max_budget": 5, "throttle_on_budget_exceeded": true}'
Defensive patterns

Strategy: validation

Validate before calling

// Only include the admin-only flag when authed as an admin
payload = {"max_budget": 5}
if caller_is_proxy_admin:  # track this where you store credentials
    payload["throttle_on_budget_exceeded"] = True
requests.post(f"{PROXY}/key/generate", headers=AUTH, json=payload)

Try / catch

try:
    resp = requests.post(f"{PROXY}/key/generate", headers=AUTH, json=payload)
    resp.raise_for_status()
except requests.HTTPError as e:
    if e.response.status_code == 403 and "throttle_on_budget_exceeded" in e.response.text:
        # retry without the flag, or escalate to an admin key
        payload.pop("throttle_on_budget_exceeded", None)
        resp = requests.post(f"{PROXY}/key/generate", headers=AUTH, json=payload)
    else:
        raise

Prevention

When it happens

Trigger: A POST /key/generate or POST /key/update request whose JSON body contains "throttle_on_budget_exceeded": true, sent with a virtual key whose role is internal_user, team_member, team_admin, or org_admin rather than proxy_admin.

Common situations: Automation scripts copy an admin-only flag from a template; a team admin tries to soften budget enforcement for their team's keys; the UI or a copied curl example includes the flag and the caller uses a non-admin key.

Related errors


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