immich-app/immich · warning · BadRequestException

Cannot leave a cluster group without any other members

Error message

Cannot leave a cluster group without any other members

What it means

Leaving a cluster group is only allowed when at least one other member remains. The service queries clusterGroupRepository.hasOtherMembers and throws this BadRequestException if the caller is the sole member, since removing the last member would orphan the group.

Solutions

  1. Add another member to the group before leaving.
  2. Delete/disband the group through the group management endpoint instead of leaving it.
  3. Verify group membership count first and show a different UI flow for single-member groups.

Example fix

// before
await api.leaveClusterGroup(groupId); // sole member → error
// after
await api.addClusterGroupMember(groupId, otherUserId); // ensure another member exists
await api.leaveClusterGroup(groupId);
Defensive patterns

Strategy: try-catch

Validate before calling

// Check remaining members before leaving
const members = await api.getClusterGroupMembers(groupId);
const others = members.filter(m => m.id !== currentUserId);
if (others.length === 0) {
  // disband group instead of leaving
}

Try / catch

try {
  await api.leaveClusterGroup(groupId);
} catch (e) {
  if (e.response?.data?.message === 'Cannot leave a cluster group without any other members') {
    await api.deleteClusterGroup(groupId); // or add a member first
  } else throw e;
}

Prevention

When it happens

Trigger: Calling the leave-cluster-group endpoint while your account is the only member of the group (hasOtherMembers returns false).

Common situations: A test/private cluster group created with just one user; other members removed earlier leaving you alone; trying to disband a group via the leave action instead of group deletion.

Understand the failure class

Background: "Invalid state transition" errors: "status must be X, actually Y", "already rejected/charging/uninstalled", "cannot ... while running" — what they mean when a library rejects your call — this error's family across 31 libraries.

Related errors


AI-assisted analysis of immich-app/immich@e55ac299a4 (2026-09-15). Data as JSON: /api/errors/80f05695ac124a9f. Report an issue: GitHub.

Appendix: source

Thrown at server/src/services/cluster-group.service.ts:92

  async regeneratePeople(auth: AuthDto, id: string) {
    await this.requireAccess({ auth, permission: Permission.ClusterGroupRead, ids: [id] });

    await this.jobRepository.queue({
      name: JobName.FacialRecognitionQueueAll,
      data: { clusterGroupId: id, force: true },
    });
  }

  async leave(auth: AuthDto, clusterGroupId: string): Promise<void> {
    await this.requireAccess({ auth, permission: Permission.ClusterGroupLeave, ids: [clusterGroupId] });

    const hasOtherMembers = await this.clusterGroupRepository.hasOtherMembers({
      clusterGroupId,
      userId: auth.user.id,
    });
    if (!hasOtherMembers) {
      throw new BadRequestException('Cannot leave a cluster group without any other members');
    }

    const clusterGroup = await this.clusterGroupRepository.create();
    await this.personRepository.reassignCluster({ userId: auth.user.id, newClusterId: clusterGroup.id });
    await this.userRepository.update(auth.user.id, { clusterGroupId: clusterGroup.id });
  }
}

View on GitHub (pinned to e55ac299a4)