{"record":{"id":"8c1bd03028f68c03","repo":"BerriAI/litellm","slug":"soft-budget-data-soft-budget-must-be-strictly","errorCode":null,"errorMessage":"soft_budget ({data.soft_budget}) must be strictly lower than max_budget ({data.max_budget})","messagePattern":"soft_budget \\((.+?)\\) must be strictly lower than max_budget \\((.+?)\\)","errorType":"http","errorClass":"HTTPException","httpStatus":400,"severity":"error","filePath":"enterprise/litellm_enterprise/proxy/management_endpoints/project_endpoints.py","lineNumber":131,"sourceCode":"    - Budget values are non-negative\n    - soft_budget < max_budget\n    \"\"\"\n    # --- Budget non-negativity checks ---\n    if data.max_budget is not None and data.max_budget < 0:\n        raise HTTPException(\n            status_code=400,\n            detail={\"error\": f\"max_budget cannot be negative. Received: {data.max_budget}\"},\n        )\n    if data.soft_budget is not None and data.soft_budget < 0:\n        raise HTTPException(\n            status_code=400,\n            detail={\"error\": f\"soft_budget cannot be negative. Received: {data.soft_budget}\"},\n        )\n\n    # --- soft_budget < max_budget ---\n    if data.soft_budget is not None and data.max_budget is not None:\n        if data.soft_budget >= data.max_budget:\n            raise HTTPException(\n                status_code=400,\n                detail={\n                    \"error\": f\"soft_budget ({data.soft_budget}) must be strictly lower than max_budget ({data.max_budget})\"\n                },\n            )\n\n    # --- Validate project models are a subset of team models ---\n    project_models = data.models\n    team_models = team_object.models or []\n    if project_models and len(team_models) > 0:\n        # If team has 'all-proxy-models', skip validation as it allows all models\n        if SpecialModelNames.all_proxy_models.value not in team_models:\n            for m in project_models:\n                if m not in team_models:\n                    raise HTTPException(\n                        status_code=400,\n                        detail={\n                            \"error\": f\"Model '{m}' not in team's allowed models. Team allowed models={team_models}. Team: {team_object.team_id}\"","sourceCodeStart":113,"sourceCodeEnd":149,"githubUrl":"https://github.com/BerriAI/litellm/blob/6c2dcb801bf2b75c18f1bb24140e7cf57465cc4d/enterprise/litellm_enterprise/proxy/management_endpoints/project_endpoints.py#L113-L149","documentation":"LiteLLM enforces that a project's soft_budget (alert threshold) is strictly lower than its max_budget (hard cap). If both are provided and soft_budget >= max_budget, the request is rejected with HTTP 400 before any DB write, because an alert threshold at or above the hard limit could never fire usefully.","triggerScenarios":"POST /project/new or PUT /project/update with both soft_budget and max_budget set where soft_budget >= max_budget, e.g. soft_budget=100 and max_budget=100 (equality also fails; the check is >=).","commonSituations":"Setting the two budgets to the same round number, swapping the fields by mistake, or scaling one budget without scaling the other during a config migration.","solutions":["Set soft_budget strictly below max_budget (e.g. 80% of max_budget)","If you swapped the fields, exchange the values and retry","Omit soft_budget (null) if you do not want threshold alerts"],"exampleFix":"// before\n{\"max_budget\": 100, \"soft_budget\": 100}\n// after\n{\"max_budget\": 100, \"soft_budget\": 80}","handlingStrategy":"validation","validationCode":"def check_budgets(p):\n    sb, mb = p.get('soft_budget'), p.get('max_budget')\n    if sb is not None and mb is not None and sb >= mb:\n        p['soft_budget'] = round(mb * 0.8, 2)  # or raise ValueError locally","typeGuard":"const budgetsConsistent = (p) =>\n  p.soft_budget == null || p.max_budget == null || p.soft_budget < p.max_budget;","tryCatchPattern":"catch (e) {\n  if (e.status === 400 && /soft_budget.*strictly lower/.test(e.body?.detail?.error ?? '')) {\n    body.soft_budget = body.max_budget * 0.8; return retry(body);\n  }\n  throw e;\n}","preventionTips":["Always derive soft_budget as a fraction (e.g. 80%) of max_budget instead of hardcoding both","Add a pre-flight assert soft < max in CI config validation"],"tags":["litellm","budget","validation","enterprise","http-400"],"backgroundTag":null,"analyzedSha":"6c2dcb801bf2b75c18f1bb24140e7cf57465cc4d","analyzedAt":"2026-08-15T07:12:03.035Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}