gravitational/teleport · error

failed to delete a role that is still in use by a user, chec

Error message

failed to delete a role that is still in use by a user, check the system server logs for more details

What it means

DeleteRole refuses to delete a role that is still referenced by at least one user. errDeleteRoleUser is returned after the auth server logs which user still uses the role; the generic message intentionally defers details to server logs. The delete is a no-op for safety.

Source

Thrown at lib/auth/access.go:106

	if err := a.emitter.EmitAuditEvent(a.closeCtx, &apievents.RoleCreate{
		Metadata: apievents.Metadata{
			Type: events.RoleCreatedEvent,
			Code: events.RoleCreatedCode,
		},
		UserMetadata: authz.ClientUserMetadata(ctx),
		ResourceMetadata: apievents.ResourceMetadata{
			Name: role.GetName(),
		},
		ConnectionMetadata: authz.ConnectionMetadata(ctx),
	}); err != nil {
		a.logger.WarnContext(ctx, "Failed to emit role create event.", "error", err)
	}
	return upserted, nil
}

var (
	errDeleteRoleUser       = errors.New("failed to delete a role that is still in use by a user, check the system server logs for more details")
	errDeleteRoleCA         = errors.New("failed to delete a role that is still in use by a certificate authority, check the system server logs for more details")
	errDeleteRoleAccessList = errors.New("failed to delete a role that is still in use by an access list, check the system server logs for more details")
)

// DeleteRole deletes a role and emits a related audit event.
func (a *Server) DeleteRole(ctx context.Context, name string) error {
	// check if this role is used by CA or Users
	users, err := a.Services.GetUsers(ctx, false)
	if err != nil {
		return trace.Wrap(err)
	}
	for _, u := range users {
		if slices.Contains(u.GetRoles(), name) {
			// Mask the actual error here as it could be used to enumerate users
			// within the system.
			a.logger.WarnContext(
				ctx, "Failed to delete role: role is still in use by a user",
				"role", name, "user", u.GetName(),

View on GitHub (pinned to 1283425b60)

Solutions

  1. Check auth server logs to find which user(s) still use the role.
  2. Remove the role from each user (update user traits/roles via tctl users update or UpdateUser) and retry DeleteRole.
  3. If the role should never have been assigned, reassign users to a replacement role first, then delete.
Defensive patterns

Strategy: type-guard

Validate before calling

users, _ := authClient.GetUsers(ctx, false)
for _, u := range users { if slices.Contains(u.GetRoles(), roleName) { return fmt.Errorf("role %q still used by user %q", roleName, u.GetName()) } }

Type guard

if errors.Is(err, auth.ErrDeleteRoleUser) { /* role in use by a user */ }

Try / catch

err := authServer.DeleteRole(ctx, roleName)
if errors.Is(err, auth.ErrDeleteRoleUser) {
    return trace.BadParameter("remove the role from all users before deleting it (see server logs)")
}

Prevention

When it happens

Trigger: Calling auth Server.DeleteRole(ctx, name) while any user's roles list contains that role name (iteration over a.Services.GetUsers finds a match).

Common situations: Admins deleting roles via tctl or the management API without realizing default or active users still carry the role; access-management automation deleting roles before unassigning them from users.

Related errors


AI-assisted analysis of gravitational/teleport@1283425b60 (2026-09-02). Data as JSON: /api/errors/0feb0d8154a1b771. Report an issue: GitHub.