{"record":{"id":"3354053b9c7049ff","repo":"BerriAI/litellm","slug":"model-m-not-in-team-s-allowed-models-team-all","errorCode":null,"errorMessage":"Model '{m}' not in team's allowed models. Team allowed models={team_models}. Team: {team_object.team_id}","messagePattern":"Model '(.+?)' not in team's allowed models\\. Team allowed models=(.+?)\\. Team: (.+?)","errorType":"http","errorClass":"HTTPException","httpStatus":400,"severity":"error","filePath":"enterprise/litellm_enterprise/proxy/management_endpoints/project_endpoints.py","lineNumber":146,"sourceCode":"    # --- 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}\"\n                        },\n                    )\n\n    # --- Validate project max_budget <= team max_budget ---\n    # Team stores budget fields directly (max_budget, tpm_limit, rpm_limit)\n    # unlike Project which uses a separate LiteLLM_BudgetTable relation\n    if data.max_budget is not None and team_object.max_budget is not None and data.max_budget > team_object.max_budget:\n        raise HTTPException(\n            status_code=400,\n            detail={\n                \"error\": f\"Project max_budget ({data.max_budget}) exceeds team's max_budget ({team_object.max_budget}). Team: {team_object.team_id}\"\n            },\n        )\n\n    # --- Validate project tpm_limit <= team tpm_limit ---","sourceCodeStart":128,"sourceCodeEnd":164,"githubUrl":"https://github.com/BerriAI/litellm/blob/6c2dcb801bf2b75c18f1bb24140e7cf57465cc4d/enterprise/litellm_enterprise/proxy/management_endpoints/project_endpoints.py#L128-L164","documentation":"A project inherits model access from its parent team; the project's models list must be a subset of the team's allowed models. If any requested model is not in the team's model list, LiteLLM rejects the request with HTTP 400 listing the offending model and the team's allowed set. Teams whose models include SpecialModelNames.all_proxy_models ('all-proxy-models') bypass this check entirely.","triggerScenarios":"POST /project/new or PUT /project/update with a \"models\" array containing a model absent from the team's models, e.g. team allows [\"gpt-4o\"] and the project requests [\"gpt-4o\", \"claude-3-5-sonnet\"]. Only fires when both the project supplies models and the team has a non-empty models list that is not 'all-proxy-models'.","commonSituations":"Adding a newly deployed model to a project before adding it to the team, model naming mismatches (alias vs deployment name), or moving a project to a more restrictive team.","solutions":["Add the missing model to the parent team first (PUT /team/update), then retry the project request","Remove the offending model from the project's models list","Set the team's models to [\"all-proxy-models\"] if the team should allow every proxy model","Verify exact model names/aliases via GET /team/info before submitting"],"exampleFix":"// before\nteam.models = [\"gpt-4o\"]\nproject.models = [\"gpt-4o\", \"claude-3-5-sonnet\"]\n// after\nteam.models = [\"gpt-4o\", \"claude-3-5-sonnet\"]\nproject.models = [\"gpt-4o\", \"claude-3-5-sonnet\"]","handlingStrategy":"validation","validationCode":"team = await client.get(f'/team/info?team_id={team_id}')\nallowed = team.teams[0].models or []\nif 'all-proxy-models' not in allowed:\n    bad = [m for m in (payload.get('models') or []) if m not in allowed]\n    if bad:\n        raise ValueError(f'models not allowed by team: {bad}; allowed: {allowed}')","typeGuard":"const modelsAreSubset = (projectModels, teamModels) =>\n  teamModels.includes('all-proxy-models') ||\n  projectModels.every((m) => teamModels.includes(m));","tryCatchPattern":"catch (e) {\n  if (e.status === 400 && /not in team's allowed models/.test(e.body?.detail?.error ?? '')) {\n    payload.models = payload.models.filter((m) => teamModels.includes(m)); return retry(payload);\n  }\n  throw e;\n}","preventionTips":["Fetch team info and diff model lists before every project create/update","Automate: new deployment -> add model to team -> then to projects, in that order"],"tags":["litellm","models","team","validation","enterprise","http-400"],"backgroundTag":null,"analyzedSha":"6c2dcb801bf2b75c18f1bb24140e7cf57465cc4d","analyzedAt":"2026-08-15T07:12:03.035Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}