BerriAI/litellm · error · HTTPException

max_budget ({_requested_max_budget}) cannot be set without s

Error message

max_budget ({_requested_max_budget}) cannot be set without specifying team_id when using a CLI session token.

What it means

LiteLLM Proxy blocks budget delegation from a CLI/UI session token (litellm login, is_session_token=true) when the caller is not a proxy admin, the request does not target a team the session token belongs to (is_ui_session_team_key false), a max_budget is set, and no resolvable team_table exists. A personal key has no team-budget enforcement at request time, so a session token cannot delegate spend authority to it.

Source

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

    # check if user set upperbound key/generate params on config.yaml
    _enforce_upperbound_key_params(data, fill_defaults=True)

    # Delegated-authority ceiling (GHSA-q775-qw9r-2r4g): a non-admin caller
    # cannot grant a key a higher budget than their own authority.
    is_ui_session_team_key = user_api_key_dict.team_id == UI_SESSION_TOKEN_TEAM_ID and _requested_team_id is not None
    # Session tokens (lite login) carry max_budget=None to avoid a per-session
    # LLM spend cap, but that None must not be read as "unlimited delegation
    # authority". A personal key (no team) has no team-budget enforcement at
    # request time, so a session token cannot delegate any budget for one.
    if (
        user_api_key_dict.is_session_token
        and user_api_key_dict.user_role != LitellmUserRoles.PROXY_ADMIN.value
        and not is_ui_session_team_key
        and _requested_max_budget is not None
        and team_table is None
    ):
        raise HTTPException(
            status_code=400,
            detail={
                "error": (
                    f"max_budget ({_requested_max_budget}) cannot be set without "
                    "specifying team_id when using a CLI session token."
                )
            },
        )
    delegation_ceiling: Final = (
        user_api_key_dict.max_budget
        if user_api_key_dict.max_budget is not None
        else (team_table.max_budget if user_api_key_dict.is_session_token and team_table is not None else None)
    )
    if (
        user_api_key_dict.user_role != LitellmUserRoles.PROXY_ADMIN.value
        and not is_ui_session_team_key
        and _requested_max_budget is not None
        and delegation_ceiling is not None

View on GitHub (pinned to 77b7c6c40c)

Solutions

  1. Add a valid "team_id" to the request body so the budget is enforced against that team at request time
  2. Drop "max_budget" from the request so no delegation is attempted
  3. Use a long-lived virtual key with delegation rights (or a proxy admin key) instead of the CLI session token

Example fix

// before
litellm --api-key $SESSION_TOKEN proxy keys create --max-budget 10

// after (delegate inside a team)
litellm --api-key $SESSION_TOKEN proxy keys create --max-budget 10 --team-id my-team-id
Defensive patterns

Strategy: validation

Validate before calling

def validate_session_token_key_request(payload: dict, is_session_token: bool) -> None:
    if is_session_token and payload.get("max_budget") is not None:
        if not payload.get("team_id"):
            raise ValueError("session-token callers must pass team_id when setting max_budget")

Try / catch

try:
    resp = requests.post(f"{PROXY}/key/generate", headers=SESSION_AUTH, json=payload)
except requests.HTTPError as e:
    if e.response.status_code == 400 and "cannot be set without specifying team_id" in e.response.text:
        payload.setdefault("team_id", resolve_default_team())
        resp = requests.post(f"{PROXY}/key/generate", headers=SESSION_AUTH, json=payload)
    else:
        raise

Prevention

When it happens

Trigger: POST /key/generate with a session token (from `litellm login`) as auth, a numeric "max_budget" in the body, and either no team_id or a team_id that does not resolve to a team row.

Common situations: CLI users scripted with `litellm login` try to mint keys programmatically the same way admin keys do; the team_id is typo'd or the team was deleted, so team_table is None; the script was originally tested with an admin key.

Related errors


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