BerriAI/litellm · error · ValueError

You must have an enterprise license to set model_max_budget.

Error message

You must have an enterprise license to set model_max_budget. You must be a LiteLLM Enterprise user to use this feature. If you have a license please set `LITELLM_LICENSE` in your env. Get a 7 day trial key here: https://www.litellm.ai/enterprise#trial. 
Pricing: https://www.litellm.ai/#pricing

What it means

model_max_budget (per-model budget limits on a key) is an enterprise feature: when a non-empty model_max_budget dict is supplied and the proxy did not verify an enterprise license (premium_user is not True), validate_model_max_budget raises. In practice this ValueError is immediately re-wrapped by the function's own except, so clients see 'Invalid model_max_budget: You must have an enterprise license...'. The check runs before the BudgetConfig structural validation.

Source

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


def validate_model_max_budget(model_max_budget: dict | None) -> None:
    """
    Validate the model_max_budget is GenericBudgetConfigType + enforce user has an enterprise license

    Raises:
        Exception: If model_max_budget is not a valid GenericBudgetConfigType
    """
    try:
        if model_max_budget is None:
            return
        if len(model_max_budget) == 0:
            return
        if model_max_budget is not None:
            from litellm.proxy.proxy_server import CommonProxyErrors, premium_user

            if premium_user is not True:
                raise ValueError(
                    f"You must have an enterprise license to set model_max_budget. {CommonProxyErrors.not_premium_user.value}"
                )
            for _model, _budget_info in model_max_budget.items():
                assert isinstance(_model, str)

                # Normalize to dict (Pydantic may already parse nested values as BudgetConfig)
                _info = _budget_info.model_dump() if hasattr(_budget_info, "model_dump") else dict(_budget_info)
                # /CRUD endpoints can pass budget_limit as a string, so we need to convert it to a float
                if "budget_limit" in _info:
                    _info["budget_limit"] = float(_info["budget_limit"])
                BudgetConfig(**_info)
    except Exception as e:
        raise ValueError(
            f"Invalid model_max_budget: {e}. Example of valid model_max_budget: https://docs.litellm.ai/docs/proxy/users"
        )

View on GitHub (pinned to 77b7c6c40c)

Solutions

  1. Obtain a license (7-day trial at litellm.ai/enterprise#trial) and export LITELLM_LICENSE in the proxy's environment, then restart
  2. Verify the license is loaded (premium_user) via startup logs or the admin UI before retrying
  3. If you do not want the feature, remove model_max_budget from the request and use the standard max_budget field instead
  4. In Kubernetes, check the secret is actually mounted into the proxy pod's env

Example fix

# before
await client.post('/key/generate', json={
    'model_max_budget': {'gpt-4o': {'budget_limit': 5, 'budget_duration': '1d'}}   # enterprise gate trips
})
# after (option 1: license)
$ export LITELLM_LICENSE='<your-enterprise-key>'   # then restart the proxy
# after (option 2: community)
await client.post('/key/generate', json={'max_budget': 5})   # single overall budget, no license needed
Defensive patterns

Strategy: fallback

Validate before calling

import os

def enterprise_enabled() -> bool:
    return bool(os.getenv('LITELLM_LICENSE'))

def key_budget_payload(max_overall: float, per_model: dict | None) -> dict:
    if per_model and not enterprise_enabled():
        return {'max_budget': max_overall}          # graceful downgrade: no per-model budgets
    return {'max_budget': max_overall, 'model_max_budget': per_model}

Try / catch

try:
    await client.post('/key/generate', json={'model_max_budget': mm, ...})
except Exception as e:
    if 'enterprise license' in str(e):
        mm.pop('model_max_budget', None)            # retry without the enterprise field
        await client.post('/key/generate', json={**payload_without_mm})
    else:
        raise

Prevention

When it happens

Trigger: POST /key/generate or CRUD key endpoints with 'model_max_budget': {'gpt-4o': {'budget_limit': 5, 'budget_duration': '1d'}} on a proxy with no or expired LITELLM_LICENSE; license env var set but invalid so premium_user stayed False.

Common situations: Copying enterprise-tier config examples into a community deployment; license key not propagated to Docker containers or Kubernetes secrets; trial license expiring between deploys.

Related errors


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