plandex-ai/plandex · warning
Cannot delete the only org owner
Error message
Cannot delete the only org owner
What it means
A deliberate guard: the target user is an org owner and numOwners == 1, so deleting them would leave the org without any owner. The handler rejects with HTTP 403 'Cannot delete the only org owner'. This protects orgs from lockout of administrative actions.
Source
Thrown at app/server/handlers/users.go:183
if err != nil {
log.Printf("Error getting org owner role id: %v\n", err)
http.Error(w, "Error getting org owner role id: "+err.Error(), http.StatusInternalServerError)
return
}
// verify user isn't the only org owner
if orgUser.OrgRoleId == orgOwnerRoleId {
numOwners, err := db.NumUsersWithRole(auth.OrgId, orgOwnerRoleId)
if err != nil {
log.Printf("Error getting number of org owners: %v\n", err)
http.Error(w, "Error getting number of org owners: "+err.Error(), http.StatusInternalServerError)
return
}
if numOwners == 1 {
log.Println("Cannot delete the only org owner")
http.Error(w, "Cannot delete the only org owner", http.StatusForbidden)
return
}
}
err = db.WithTx(r.Context(), "delete org user", func(tx *sqlx.Tx) error {
err = db.DeleteOrgUser(auth.OrgId, userId, tx)
if err != nil {
log.Println("Error deleting org user: ", err)
return fmt.Errorf("error deleting org user: %v", err)
}
invite, err := db.GetActiveInviteByEmail(auth.OrgId, auth.User.Email)
if err != nil {
log.Println("Error getting invite for org user: ", err)
return fmt.Errorf("error getting invite for org user: %v", err)View on GitHub (pinned to e2d772072e)
Solutions
- Promote another member to the owner role first, then delete the target owner
- If the caller is the last owner removing themselves, transfer ownership instead
- Adjust automation scripts to skip or handle users whose org_role_id equals the owner role id
- If the org should be decommissioned, delete the org itself rather than its last owner
Example fix
// before
DELETE /org-users/user-123 // user-123 is the only owner -> 403
// after
POST /org-users/owner-transfer {"newOwnerId": "user-456"}
DELETE /org-users/user-123 // now succeeds Defensive patterns
Strategy: validation
Validate before calling
var ownerCount int
db.Get(&ownerCount,
"SELECT COUNT(*) FROM org_users WHERE org_id=$1 AND org_role_id=$2",
orgId, ownerRoleId)
if targetRoleId == ownerRoleId && ownerCount <= 1 {
return errors.New("cannot remove the only org owner; transfer ownership first")
} Type guard
func isSoleOwner(db *sqlx.DB, userId, orgId, ownerRoleId string) bool {
var role string
var n int
_ = db.Get(&role, "SELECT org_role_id FROM org_users WHERE user_id=$1 AND org_id=$2", userId, orgId)
if role != ownerRoleId { return false }
_ = db.Get(&n, "SELECT COUNT(*) FROM org_users WHERE org_id=$1 AND org_role_id=$2", orgId, ownerRoleId)
return n <= 1
} Try / catch
if resp.StatusCode == http.StatusForbidden &&
strings.Contains(body, "Cannot delete the only org owner") {
// prompt user to promote a co-owner first, do not retry
return errLastOwner
} Prevention
- Before removing an owner, promote at least one other member to owner role
- Handle self-removal of the last owner via an explicit ownership-transfer flow
- Make bulk cleanup scripts query org_role_id and skip sole owners
- Surface this 403 distinctly in UIs with a 'transfer ownership first' prompt
When it happens
Trigger: DELETE request for the sole user holding the org owner role in the org — the only remaining owner is targeted for removal.
Common situations: Downsizing a team where the founder is the last owner; scripted cleanup scripts deleting users indiscriminately; owner trying to delete themselves when no co-owner exists.
Related errors
- User does not have permission to remove user with role: {org
- User {userId} is not a member of org {auth.OrgId}
- error validating project membership: %v
- error checking if project exists: %v
- error validating project
AI-assisted analysis of plandex-ai/plandex@e2d772072e (2026-09-05).
Data as JSON: /api/errors/b6e30dfccdf49c16.
Report an issue: GitHub.