BerriAI/litellm · error · HTTPException

Project rpm_limit ( ) exceeds team's rpm_limit ( )

Error message

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

What it means

Rate-limit guard in _check_team_project_limits: a project's rpm_limit may not exceed its team's rpm_limit when the team has one set; otherwise HTTP 400 with both values. Same envelope pattern as the tpm check directly above it.

Solutions

  1. Lower the project rpm_limit to <= the team's
  2. Raise the team's rpm_limit first, then retry
  3. Omit the project rpm_limit to inherit the team's limit

Example fix

# before
team rpm_limit: 1000
project payload: {"rpm_limit": 5000}

# after
team rpm_limit: 5000 (raised via /team/update)
project payload: {"rpm_limit": 5000}
Defensive patterns

Strategy: validation

Validate before calling

team = await get(f"/team/info?team_id={data['team_id']}")
team_rpm = team["team_info"].get("rpm_limit")
if team_rpm is not None and data.get("rpm_limit") is not None and data["rpm_limit"] > team_rpm:
    raise ValueError(f"project rpm_limit must be <= team rpm_limit ({team_rpm})")

Try / catch

try:
    await post("/project/new", json=data)
except HTTPStatusError as e:
    if e.response.status_code == 400 and "rpm_limit" in e.response.text:
        data["rpm_limit"] = min(data["rpm_limit"], team_rpm)
        retry()
    raise

Prevention

When it happens

Trigger: POST/PUT project with rpm_limit 5000 when the team's rpm_limit is 1000.

Common situations: Bursty workloads moved under a project without raising the team cap; copy-pasted project configs from teams with looser limits.

Related errors


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

Appendix: source

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

        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: dict[str, object] = data.model_dump(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 77b7c6c40c)