BerriAI/litellm · error · HTTPException

Project rpm_limit ({data.rpm_limit}) exceeds team's rpm_limi

Error message

Project rpm_limit ({data.rpm_limit}) exceeds team's rpm_limit ({team_object.rpm_limit})

What it means

A project's rpm_limit (requests-per-minute rate limit) must not exceed its parent team's rpm_limit. When both values are set and the project's is larger, LiteLLM returns HTTP 400 from _check_team_project_limits. This keeps project-level rate limits inside the team's throttling envelope.

Source

Thrown at enterprise/litellm_enterprise/proxy/management_endpoints/project_endpoints.py:175

        raise HTTPException(
            status_code=400,
            detail={
                "error": f"Project max_budget ({data.max_budget}) exceeds team's max_budget ({team_object.max_budget}). Team: {team_object.team_id}"
            },
        )

    # --- Validate project tpm_limit <= team tpm_limit ---
    if data.tpm_limit is not None and team_object.tpm_limit is not None and data.tpm_limit > team_object.tpm_limit:
        raise HTTPException(
            status_code=400,
            detail={
                "error": f"Project tpm_limit ({data.tpm_limit}) exceeds team's tpm_limit ({team_object.tpm_limit}). Team: {team_object.team_id}"
            },
        )

    # --- Validate project rpm_limit <= team rpm_limit ---
    if data.rpm_limit is not None and team_object.rpm_limit is not None and data.rpm_limit > team_object.rpm_limit:
        raise HTTPException(
            status_code=400,
            detail={
                "error": f"Project rpm_limit ({data.rpm_limit}) exceeds team's rpm_limit ({team_object.rpm_limit}). Team: {team_object.team_id}"
            },
        )


async def _create_budget_for_project(
    data: NewProjectRequest,
    user_id: str | None,
    litellm_proxy_admin_name: str,
    prisma_client: PrismaClient,
) -> str:
    """Create a budget for the project and return budget_id."""
    budget_params = LiteLLM_BudgetTable.model_fields.keys()
    _json_data: Mapping[str, object] = data.json(exclude_none=True)
    _budget_data = {k: v for k, v in _json_data.items() if k in budget_params}
    budget_row = LiteLLM_BudgetTable.model_validate(_budget_data)

View on GitHub (pinned to 6c2dcb801b)

Solutions

  1. Set the project's rpm_limit to at most the team's rpm_limit
  2. Increase the team's rpm_limit first (PUT /team/update), then retry
  3. Omit rpm_limit from the project payload to inherit team throttling

Example fix

// before
team.rpm_limit = 100
project payload: {"rpm_limit": 1000}
// after
team.rpm_limit = 2000
project payload: {"rpm_limit": 1000}
Defensive patterns

Strategy: validation

Validate before calling

team = await client.get(f'/team/info?team_id={payload["team_id"]}')
team_rpm = team.teams[0].rpm_limit
if payload.get('rpm_limit') is not None and team_rpm is not None and payload['rpm_limit'] > team_rpm:
    payload['rpm_limit'] = team_rpm  # cap at team limit, or raise team first

Type guard

const withinTeamRpm = (p, team) =>
  p.rpm_limit == null || team.rpm_limit == null || p.rpm_limit <= team.rpm_limit;

Prevention

When it happens

Trigger: POST /project/new or PUT /project/update where data.rpm_limit > team_object.rpm_limit and both are non-null, e.g. team rpm_limit=100 and project rpm_limit=1000. Either side being None skips the check.

Common situations: Raising a project's request throughput without raising the team cap, or duplicating a project config from a high-limit team into a low-limit team.

Related errors


AI-assisted analysis of BerriAI/litellm@6c2dcb801b (2026-08-15). Data as JSON: /api/errors/f90a1ff15a22860b. Report an issue: GitHub.