{"record":{"id":"db2a7e897ea0284a","repo":"BerriAI/litellm","slug":"team-id-is-required-when-ptu-fields-are-set-one-m","errorCode":null,"errorMessage":"team_id is required when PTU fields are set (one model maps to one team)","messagePattern":"team_id is required when PTU fields are set \\(one model maps to one team\\)","errorType":"http","errorClass":"HTTPException","httpStatus":400,"severity":"error","filePath":"litellm/proxy/management_endpoints/model_management_endpoints.py","lineNumber":340,"sourceCode":"        raise HTTPException(status_code=400, detail=\"ptu_effective_to must be after ptu_effective_from\")\n\n    has_count: Final = model_info.get(\"ptu_count\") is not None\n    has_rate: Final = model_info.get(\"cost_per_ptu_per_hour\") is not None\n    if not has_count and not has_rate:\n        return\n    if has_count != has_rate:\n        raise HTTPException(status_code=400, detail=\"ptu_count and cost_per_ptu_per_hour must be set together\")\n    if effective_from is None:\n        raise HTTPException(\n            status_code=400,\n            detail=(\n                \"ptu_effective_from is required when PTU fields are set. Flat cost accrues from that \"\n                \"instant, so without it the start would have to be inferred and a deployment configured \"\n                \"today could be billed for days it did not exist\"\n            ),\n        )\n    if not model_info.get(\"team_id\"):\n        raise HTTPException(\n            status_code=400, detail=\"team_id is required when PTU fields are set (one model maps to one team)\"\n        )\n\n\n# The mirrored per-token pricing fields plus the three remaining fields\n# Router._inherit_builtin_cache_pricing back-fills from the public cost map. An unset field is\n# what that back-fill targets, so a field left out here is one a PTU deployment still bills.\n# tiered_pricing is the one mirrored field that is a table of ranges, not a rate, so it is stored\n# empty (see _PTU_EMPTIED_PRICING_FIELDS): its tiers outrank the zeros written beside them, so\n# dropping it would leave the cost map's tiers billing the traffic the reserved capacity covers.\n_PTU_ZEROED_PRICING_FIELDS: Final = tuple(f for f in SPECIAL_MODEL_INFO_PARAMS if f != \"tiered_pricing\") + (\n    \"cache_creation_input_token_cost_above_1hr\",\n    \"cache_creation_input_token_cost_above_200k_tokens\",\n    \"cache_read_input_token_cost_above_200k_tokens\",\n)\n_PTU_EMPTIED_PRICING_FIELDS: Final = frozenset({\"tiered_pricing\"})\n_PTU_ZEROED_PRICING: Final[Mapping[str, float | tuple[()]]] = MappingProxyType(\n    {","sourceCodeStart":322,"sourceCodeEnd":358,"githubUrl":"https://github.com/BerriAI/litellm/blob/77b7c6c40c0c5aa5fbcb1d6a1825ac39ca8829b8/litellm/proxy/management_endpoints/model_management_endpoints.py#L322-L358","documentation":"Attribution guard on PTU model_info: PTU count/rate fields are set but no team_id is present. PTU billing maps one model to exactly one owning team, so without team_id the flat cost cannot be attributed; rejected with 400 at write time.","triggerScenarios":"Thrown at litellm/proxy/management_endpoints/model_management_endpoints.py:340 when the library encounters an invalid state.","commonSituations":"See trigger scenarios.","solutions":["Provide team_id in model_info when setting PTU fields."],"exampleFix":null,"handlingStrategy":"validation","validationCode":null,"typeGuard":null,"tryCatchPattern":null,"preventionTips":[],"tags":[],"backgroundTag":null,"analyzedSha":"77b7c6c40c0c5aa5fbcb1d6a1825ac39ca8829b8","analyzedAt":"2026-08-18T11:44:31.656Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-14T00:17:10.932Z"}