plandex-ai/plandex · error
error deleting org user: %v
Error message
error deleting org user: %v
What it means
The org-user deletion handler runs db.DeleteOrgUser inside db.WithTx. If the delete fails, the transaction is rolled back and the error is wrapped as 'error deleting org user', returning HTTP 500 to the caller.
Source
Thrown at app/server/handlers/users.go:194
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)
}
if invite != nil {
err = db.DeleteInvite(invite.Id, tx)
if err != nil {
log.Println("Error deleting invite: ", err)
return fmt.Errorf("error deleting invite: %v", err)
}
}
View on GitHub (pinned to e2d772072e)
Solutions
- Inspect the wrapped cause; FK violations are the usual culprit.
- Delete or reassign dependent rows (plans, streams) before removing the org user.
- Add ON DELETE CASCADE or an explicit cleanup in the same transaction.
- Guard against double-delete by checking membership before deleting.
Example fix
// before
err = db.DeleteOrgUser(auth.OrgId, userId, tx)
// after
if _, err := db.GetOrgUser(auth.OrgId, userId); err != nil {
return fmt.Errorf("org user not found")
}
err = db.DeleteOrgUser(auth.OrgId, userId, tx) Defensive patterns
Strategy: validation
Validate before calling
// Go - verify membership and no dependents before deleting
if _, err := db.GetOrgUser(auth.OrgId, userId); err != nil {
return fmt.Errorf("user is not a member of this org")
} Try / catch
err = db.WithTx(ctx, "delete org user", func(tx *sqlx.Tx) error {
if err := db.DeleteOrgUser(auth.OrgId, userId, tx); err != nil {
if isForeignKeyErr(err) {
return errUserHasDependents
}
return fmt.Errorf("error deleting org user: %v", err)
}
return nil
}) Prevention
- Remove/reassign dependent rows (plans, streams) before deleting users.
- Use ON DELETE CASCADE for org_user-owned child rows.
- Make deletion idempotent to survive double-DELETE races.
- Verify the user belongs to the org before attempting deletion.
When it happens
Trigger: db.DeleteOrgUser fails: FK constraints from rows still referencing the org_user (plans, streams, assignments), non-existent org/user pair, permission/ownership violation, deadlock, or DB connection loss.
Common situations: Removing a user who still owns or is assigned to plans/branches; deleting an already-removed member (double DELETE); cascade rules missing in the schema.
Related errors
- error invalidating conflicted results: %v
- error adding plan context tokens: %v
- error creating invite: %v
- error deleting invite: %v
- error deleting model pack: %v
AI-assisted analysis of plandex-ai/plandex@e2d772072e (2026-09-05).
Data as JSON: /api/errors/215957eb59d6f48d.
Report an issue: GitHub.