BerriAI/litellm · error · ProxyException

400

400

Error message

Project id = {data.project_id} already exists. Please use a different project id.

What it means

When a client supplies an explicit project_id on POST /project/new, LiteLLM checks litellm_projecttable.find_unique for a collision and throws a ProxyException (type bad_request, code 400, param project_id) if the id already exists. Omitting project_id is safe: the server generates a fresh uuid4 that cannot collide in practice.

Source

Thrown at enterprise/litellm_enterprise/proxy/management_endpoints/project_endpoints.py:403

        if not has_permission:
            raise HTTPException(
                status_code=403,
                detail={
                    "error": f"Only admins or team admins can create projects. Your role is {user_api_key_dict.user_role}"
                },
            )

        # Generate project_id if not provided
        if data.project_id is None:
            data.project_id = str(uuid.uuid4())
        else:
            # Check if project_id already exists
            existing_project = await prisma_client.db.litellm_projecttable.find_unique(
                where={"project_id": data.project_id}
            )
            if existing_project is not None:
                raise ProxyException(
                    message=f"Project id = {data.project_id} already exists. Please use a different project id.",
                    type="bad_request",
                    code=400,
                    param="project_id",
                )

        # Create budget if not provided
        if data.budget_id is None:
            data.budget_id = await _create_budget_for_project(
                data=data,
                user_id=user_api_key_dict.user_id,
                litellm_proxy_admin_name=litellm_proxy_admin_name,
                prisma_client=prisma_client,
            )

        ## Handle Object Permission - MCP, Vector Stores etc.
        object_permission_id = await _set_project_object_permission(
            data=data,

View on GitHub (pinned to 6c2dcb801b)

Solutions

  1. Use a different project_id or omit the field and let the server generate a uuid
  2. Make provisioning scripts check GET /project/info (or catch 400 on project_id) before creating
  3. On retry-after-timeout, verify the project was not already created before resubmitting the same id

Example fix

# before
curl -X POST .../project/new -d '{"project_id":"project-123","team_id":"t1"}'
# after
curl -X POST .../project/new -d '{"team_id":"t1"}'  # server assigns a uuid project_id
Defensive patterns

Strategy: try-catch

Validate before calling

try:
    await client.get(f'/project/info?project_id={payload["project_id"]}')
    raise RuntimeError('project_id already exists; use update instead')
except Exception as e:
    if getattr(e, 'status_code', None) != 404:
        raise

Try / catch

catch (e) {
  if (e.status === 400 && /already exists/.test(e.body?.detail?.error ?? e.message ?? '')) {
    return client.put('/project/update', body); // idempotent apply: switch to update
  }
  throw e;
}

Prevention

When it happens

Trigger: POST /project/new with a "project_id" that already exists in the database, e.g. re-running an idempotent provisioning script that specifies project_id after a successful first run.

Common situations: Terraform/Ansible or CI jobs re-applying project creation, retrying a request that actually succeeded server-side, or copying an environment's ids into another without dedup.

Related errors


AI-assisted analysis of BerriAI/litellm@6c2dcb801b (2026-08-15). Data as JSON: /api/errors/a39b6fcbd028a646. Report an issue: GitHub.