{"record":{"id":"fa962819f2951ef9","repo":"BerriAI/litellm","slug":"max-budget-requested-max-budget-cannot-be-set","errorCode":null,"errorMessage":"max_budget ({_requested_max_budget}) cannot be set without specifying team_id when using a CLI session token.","messagePattern":"max_budget \\((.+?)\\) cannot be set without specifying team_id when using a CLI session token\\.","errorType":"http","errorClass":"HTTPException","httpStatus":400,"severity":"error","filePath":"litellm/proxy/management_endpoints/key_management_endpoints.py","lineNumber":936,"sourceCode":"\n    # check if user set upperbound key/generate params on config.yaml\n    _enforce_upperbound_key_params(data, fill_defaults=True)\n\n    # Delegated-authority ceiling (GHSA-q775-qw9r-2r4g): a non-admin caller\n    # cannot grant a key a higher budget than their own authority.\n    is_ui_session_team_key = user_api_key_dict.team_id == UI_SESSION_TOKEN_TEAM_ID and _requested_team_id is not None\n    # Session tokens (lite login) carry max_budget=None to avoid a per-session\n    # LLM spend cap, but that None must not be read as \"unlimited delegation\n    # authority\". A personal key (no team) has no team-budget enforcement at\n    # request time, so a session token cannot delegate any budget for one.\n    if (\n        user_api_key_dict.is_session_token\n        and user_api_key_dict.user_role != LitellmUserRoles.PROXY_ADMIN.value\n        and not is_ui_session_team_key\n        and _requested_max_budget is not None\n        and team_table is None\n    ):\n        raise HTTPException(\n            status_code=400,\n            detail={\n                \"error\": (\n                    f\"max_budget ({_requested_max_budget}) cannot be set without \"\n                    \"specifying team_id when using a CLI session token.\"\n                )\n            },\n        )\n    delegation_ceiling: Final = (\n        user_api_key_dict.max_budget\n        if user_api_key_dict.max_budget is not None\n        else (team_table.max_budget if user_api_key_dict.is_session_token and team_table is not None else None)\n    )\n    if (\n        user_api_key_dict.user_role != LitellmUserRoles.PROXY_ADMIN.value\n        and not is_ui_session_team_key\n        and _requested_max_budget is not None\n        and delegation_ceiling is not None","sourceCodeStart":918,"sourceCodeEnd":954,"githubUrl":"https://github.com/BerriAI/litellm/blob/77b7c6c40c0c5aa5fbcb1d6a1825ac39ca8829b8/litellm/proxy/management_endpoints/key_management_endpoints.py#L918-L954","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","solutions":["Add a valid \"team_id\" to the request body so the budget is enforced against that team at request time","Drop \"max_budget\" from the request so no delegation is attempted","Use a long-lived virtual key with delegation rights (or a proxy admin key) instead of the CLI session token"],"exampleFix":"// before\nlitellm --api-key $SESSION_TOKEN proxy keys create --max-budget 10\n\n// after (delegate inside a team)\nlitellm --api-key $SESSION_TOKEN proxy keys create --max-budget 10 --team-id my-team-id","handlingStrategy":"validation","validationCode":"def validate_session_token_key_request(payload: dict, is_session_token: bool) -> None:\n    if is_session_token and payload.get(\"max_budget\") is not None:\n        if not payload.get(\"team_id\"):\n            raise ValueError(\"session-token callers must pass team_id when setting max_budget\")","typeGuard":null,"tryCatchPattern":"try:\n    resp = requests.post(f\"{PROXY}/key/generate\", headers=SESSION_AUTH, json=payload)\nexcept requests.HTTPError as e:\n    if e.response.status_code == 400 and \"cannot be set without specifying team_id\" in e.response.text:\n        payload.setdefault(\"team_id\", resolve_default_team())\n        resp = requests.post(f\"{PROXY}/key/generate\", headers=SESSION_AUTH, json=payload)\n    else:\n        raise","preventionTips":["Use a dedicated virtual key (not the CLI session token) for programmatic key management","Wrap `litellm login` tokens in tooling that always attaches a team_id when budgets are involved","Document that personal (team-less) keys cannot receive delegated budgets from session tokens"],"tags":["litellm-proxy","session-token","budget-delegation","virtual-keys","key-management"],"backgroundTag":"budget-delegation-denied","analyzedSha":"77b7c6c40c0c5aa5fbcb1d6a1825ac39ca8829b8","analyzedAt":"2026-08-18T11:44:31.656Z","schemaVersion":2},"datasetVersion":"2026-08-21T13:17:26.733Z"}