Significant-Gravitas/AutoGPT · error · ValueError

Cannot remove the last workspace admin. Promote another memb

Error message

Cannot remove the last workspace admin. Promote another member to admin first.

What it means

Raised by the remove-member flow in team_db when the member being removed is an ACTIVE admin and the workspace has admin_count <= 1. It prevents a workspace from becoming unmanageable with no one able to administer it. Plain ValueError from the DB layer.

Source

Thrown at autogpt_platform/backend/backend/api/features/orgs/team_db.py:223

    members = await list_team_members(ws_id)
    return next(m for m in members if m.user_id == user_id)


async def remove_team_member(ws_id: str, user_id: str) -> None:
    """Remove a member from a workspace.

    Guards against removing the last admin — workspace would become unmanageable.
    """
    # Check if this would remove the last admin
    member = await prisma.teammember.find_unique(
        where={"teamId_userId": {"teamId": ws_id, "userId": user_id}}
    )
    if member and member.isAdmin:
        admin_count = await prisma.teammember.count(
            where={"teamId": ws_id, "isAdmin": True, "status": "ACTIVE"}
        )
        if admin_count <= 1:
            raise ValueError(
                "Cannot remove the last workspace admin. "
                "Promote another member to admin first."
            )

    await prisma.teammember.delete(
        where={"teamId_userId": {"teamId": ws_id, "userId": user_id}}
    )

View on GitHub (pinned to 9c8bb5550f)

Solutions

  1. Promote another ACTIVE member to admin first (update member with isAdmin=true), then retry the removal
  2. If everyone else should not be admin, invite/add a new admin and then remove yourself
  3. Transfer ownership: make sure the promote happens and is committed (ACTIVE status) before the remove call
  4. In automated flows, sequence operations as promote -> verify admin_count >= 2 -> remove

Example fix

# before
await remove_team_member(ws_id, sole_admin_id)  # raises: last admin
# after
await update_team_member(ws_id, other_member_id, data={"isAdmin": True})
await remove_team_member(ws_id, sole_admin_id)
Defensive patterns

Strategy: validation

Validate before calling

const admins = (await listMembers(orgId, wsId)).filter(m => m.isAdmin && m.status === 'ACTIVE');
if (admins.length <= 1 && admins[0]?.userId === targetUserId) {
  throw new Error('Promote another admin before removing the last one');
}

Type guard

function isLastActiveAdmin(m: TeamMemberResponse, activeAdmins: TeamMemberResponse[]): boolean {
  return m.isAdmin && m.status === 'ACTIVE' && activeAdmins.length <= 1;
}

Try / catch

try {
  await removeTeamMember(orgId, wsId, userId);
} catch (e) {
  if (e.message.includes('last workspace admin')) {
    await updateTeamMember(orgId, wsId, successorId, { isAdmin: true });
    await removeTeamMember(orgId, wsId, userId);
  } else throw e;
}

Prevention

When it happens

Trigger: DELETE or remove call for a workspace member (team_db remove path around team_db.py:223) where that member has isAdmin=true and is the only ACTIVE admin in the workspace. Note the guard triggers on ANY removal path that hits it (delete member, and any flow reusing this check), including the member removing themselves.

Common situations: Sole admin tries to leave/remove themselves without promoting a successor; org downsizing removes the only admin; admin demotes then removes themselves in the wrong order; tests that never promote a second admin.

Related errors


AI-assisted analysis of Significant-Gravitas/AutoGPT@9c8bb5550f (2026-08-14). Data as JSON: /api/errors/2503456e7efe3119. Report an issue: GitHub.