{"record":{"id":"a6233e05d071ec22","repo":"BerriAI/litellm","slug":"soft-budget-cannot-be-negative-received-data-so","errorCode":null,"errorMessage":"soft_budget cannot be negative. Received: {data.soft_budget}","messagePattern":"soft_budget cannot be negative\\. Received: (.+?)","errorType":"http","errorClass":"HTTPException","httpStatus":400,"severity":"error","filePath":"enterprise/litellm_enterprise/proxy/management_endpoints/project_endpoints.py","lineNumber":148,"sourceCode":"\n    Mirrors _check_org_team_limits() from team_endpoints.py.\n\n    Validates:\n    - Project models are a subset of Team models\n    - Project max_budget <= Team max_budget\n    - Project tpm_limit <= Team tpm_limit\n    - Project rpm_limit <= Team rpm_limit\n    - 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: list[str] = team_object.models or []\n    if project_models and len(team_models) > 0:","sourceCodeStart":130,"sourceCodeEnd":166,"githubUrl":"https://github.com/BerriAI/litellm/blob/77b7c6c40c0c5aa5fbcb1d6a1825ac39ca8829b8/enterprise/litellm_enterprise/proxy/management_endpoints/project_endpoints.py#L130-L166","documentation":"Companion check in _check_team_project_limits: soft_budget < 0 returns HTTP 400 with the received value. soft_budget is the early-warning threshold under max_budget, so negative values are rejected outright.","triggerScenarios":"POST /project/new or /project/update with \"soft_budget\": -1 or any negative number.","commonSituations":"Same sentinel-value mistakes as max_budget: clients defaulting unset numbers to -1, or computed thresholds going negative after budget consumption.","solutions":["Omit soft_budget (null is allowed) or send a non-negative value","If no early-warning threshold is wanted, leave soft_budget unset rather than negative","Fix the client code that computes soft_budget so it clamps at 0 or omits"],"exampleFix":"# before\n{\"project_alias\": \"p1\", \"soft_budget\": -5}\n\n# after\n{\"project_alias\": \"p1\", \"soft_budget\": 80}","handlingStrategy":"validation","validationCode":"def sanitize_project_payload(data: dict) -> dict:\n    sb = data.get(\"soft_budget\")\n    if sb is not None and sb < 0:\n        raise ValueError(f\"soft_budget must be >= 0, got {sb}\")\n    return data","typeGuard":"def is_valid_budget(v) -> bool:\n    return v is None or (isinstance(v, (int, float)) and not isinstance(v, bool) and v >= 0)","tryCatchPattern":"try:\n    await post(\"/project/new\", json=data)\nexcept HTTPStatusError as e:\n    if e.response.status_code == 400 and \"cannot be negative\" in e.response.text:\n        data.pop(\"soft_budget\", None)  # unset instead of negative\n        retry()\n    raise","preventionTips":["Omit optional budget fields rather than sending sentinels","Clamp computed thresholds at 0 before submitting"],"tags":["litellm","projects","budget","validation","http-400"],"backgroundTag":"request-validation-failed","analyzedSha":"77b7c6c40c0c5aa5fbcb1d6a1825ac39ca8829b8","analyzedAt":"2026-08-18T11:44:31.656Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}