{"record":{"id":"d8877341ca4afbcd","repo":"BerriAI/litellm","slug":"project-id-is-required","errorCode":null,"errorMessage":"project_id is required","messagePattern":"project_id is required","errorType":"http","errorClass":"HTTPException","httpStatus":400,"severity":"error","filePath":"enterprise/litellm_enterprise/proxy/management_endpoints/project_endpoints.py","lineNumber":581,"sourceCode":"\n        # ADD METADATA FIELDS\n        for field in LiteLLM_ManagementEndpoint_MetadataFields_Premium:\n            if getattr(data, field, None) is not None:\n                _set_object_metadata_field(\n                    object_data=data,\n                    field_name=field,\n                    value=getattr(data, field),\n                )\n                delattr(data, field)\n\n        if prisma_client is None:\n            raise HTTPException(\n                status_code=500,\n                detail={\"error\": CommonProxyErrors.db_not_connected_error.value},\n            )\n\n        if data.project_id is None:\n            raise HTTPException(\n                status_code=400,\n                detail={\"error\": \"project_id is required\"},\n            )\n\n        # Fetch existing project\n        existing_project: (\n            prisma_models.LiteLLM_ProjectTable | None\n        ) = await _project_table(prisma_client).find_unique(where={\"project_id\": data.project_id})\n\n        if existing_project is None:\n            raise ProxyException(\n                message=f\"Project not found, project_id={data.project_id}\",\n                type=\"not_found\",\n                code=404,\n                param=\"project_id\",\n            )\n\n        # Permission to *edit* the project must be evaluated against the","sourceCodeStart":563,"sourceCodeEnd":599,"githubUrl":"https://github.com/BerriAI/litellm/blob/77b7c6c40c0c5aa5fbcb1d6a1825ac39ca8829b8/enterprise/litellm_enterprise/proxy/management_endpoints/project_endpoints.py#L563-L599","documentation":"Update requires the client to name which project to change. Unlike create (which can auto-generate an id), update has no default: a payload where project_id is None — missing, null, or empty — is rejected with 400 immediately after the DB check, before any row is fetched.","triggerScenarios":"POST /project/update with project_id absent or explicitly null in the JSON body.","commonSituations":"Client models serialized with exclude_none=True so the field never reaches the wire; copy-pasting a create payload into an update call; UIs that keep a blank 'current project' field.","solutions":["Include project_id in the update payload — copy it from GET /project/list or the create response","If using a serialization layer, disable exclude_none for this call so set ids are not dropped","Log the outgoing payload at DEBUG before sending to catch silently-dropped required fields"],"exampleFix":"# before (400: project_id is required)\nhttpx.post(base + '/project/update', headers=hdr, json={'project_name': 'new-name'})\n\n# after\nhttpx.post(base + '/project/update', headers=hdr, json={'project_id': 'p1', 'project_name': 'new-name'})","handlingStrategy":"validation","validationCode":"def validate_update_payload(payload: dict) -> None:\n    pid = payload.get('project_id')\n    if not isinstance(pid, str) or not pid.strip():\n        raise ValueError('/project/update requires a non-empty string project_id')\n\nvalidate_update_payload(payload)\nhttpx.post(base + '/project/update', headers=hdr, json=payload)","typeGuard":"def is_valid_update_payload(p: dict) -> bool:\n    return isinstance(p, dict) and isinstance(p.get('project_id'), str) and len(p['project_id'].strip()) > 0","tryCatchPattern":"except httpx.HTTPStatusError as e:\n    if e.response.status_code == 400 and 'project_id is required' in e.response.text:\n        raise ValueError('update payload dropped project_id; check serialization (exclude_none)') from None","preventionTips":["Always fetch the project id from create/list responses before composing updates","Beware serializers configured with exclude_none=True dropping required fields","Unit-test request payloads against the endpoint schema in CI"],"tags":["litellm","validation","http-400","projects"],"backgroundTag":"missing-required-argument","analyzedSha":"77b7c6c40c0c5aa5fbcb1d6a1825ac39ca8829b8","analyzedAt":"2026-08-18T11:44:31.656Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}