langfuse/langfuse · error

Cannot delete organization with existing projects

Error message

Cannot delete organization with existing projects

What it means

Returned as HTTP 400 when deleting an organization that still has one or more non-deleted projects (prisma.project.count where deletedAt: null > 0). The API refuses deletion until all projects are removed or transferred.

Source

Thrown at web/src/ee/features/admin-api/server/organizations/organizationById.ts:184

  }

  // count non-deleted projects
  const countNonDeletedProjects = await prisma.project.count({
    where: {
      orgId: organizationId,
      deletedAt: null,
    },
  });

  // count all projects (including soft-deleted)
  const countAllProjects = await prisma.project.count({
    where: {
      orgId: organizationId,
    },
  });

  if (countNonDeletedProjects > 0) {
    return res.status(400).json({
      error: "Cannot delete organization with existing projects",
      message:
        "Please delete or transfer all projects before deleting the organization.",
    });
  }

  if (countAllProjects > 0) {
    return res.status(400).json({
      error: "Cannot delete organization with existing projects",
      message:
        "Deletion of your projects is still being processed, please try deleting the organization later",
    });
  }

  // Delete the organization
  const deletedOrganization = await prisma.organization.delete({
    where: { id: organizationId },
  });

View on GitHub (pinned to 59d92c7cf3)

Solutions

  1. Delete (or transfer) every project in the organization first via the admin projects API
  2. Re-check with the list projects endpoint until zero active projects remain
  3. Then retry the organization delete

Example fix

// before
await adminApi.del(`/organizations/${orgId}`);
// after
for (const p of await listProjects(orgId)) await adminApi.del(`/organizations/${orgId}/projects/${p.id}`);
await adminApi.del(`/organizations/${orgId}`);
Defensive patterns

Strategy: validation

Validate before calling

const projects = await listProjects(orgId).then(ps => ps.filter(p => !p.deletedAt));
if (projects.length > 0) throw new Error(`delete ${projects.length} projects first`);

Try / catch

if (res.status === 400 && /existing projects/.test(body)) { await deleteAllProjects(orgId); retry; }

Prevention

When it happens

Trigger: DELETE /api/admin/organizations/:id while any project in the org has deletedAt = null.

Common situations: Forgetting to delete projects first in teardown scripts; soft-deleted-but-still-active projects; new projects created after the pre-delete listing.

Related errors


AI-assisted analysis of langfuse/langfuse@59d92c7cf3 (2026-08-27). Data as JSON: /api/errors/c1e5fc0ec16f9c5b. Report an issue: GitHub.