gravitational/teleport · error

failed to delete a role that is still in use by a certificat

Error message

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

What it means

DeleteRole also refuses deletion when the role is referenced by a certificate authority. errDeleteRoleCA is returned when any CA's role list includes the role; details (which CA) are written to server logs. This preserves CA trust configuration consistency.

Source

Thrown at lib/auth/access.go:107

	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. Inspect auth server logs to identify which CA still references the role.
  2. Update the CA resource to remove/replace the role (e.g. via UpsertCertAuthority) then retry DeleteRole.
  3. Verify with `tctl get cert_authority` which CAs mention the role before deleting.
Defensive patterns

Strategy: type-guard

Validate before calling

cas := authClient.GetCertAuthorities(ctx, caType, false)
for _, ca := range cas { if slices.Contains(ca.GetRoles(), roleName) { return fmt.Errorf("role %q used by CA %q", roleName, ca.GetClusterName()) } }

Type guard

if errors.Is(err, auth.ErrDeleteRoleCA) { /* role in use by a certificate authority */ }

Try / catch

err := authServer.DeleteRole(ctx, roleName)
if errors.Is(err, auth.ErrDeleteRoleCA) {
    return trace.BadParameter("remove the role from all certificate authorities before deleting it")
}

Prevention

When it happens

Trigger: Calling Server.DeleteRole(ctx, name) while any cert authority resource (e.g. gotten via the CA service) lists the role among its roles, at lib/auth/access.go:143.

Common situations: Deleting a role used by a bot/CA trust configuration; migrations that reassign CA roles being run out of order; manually edited CA resources retaining stale role references.

Understand the failure class

Related errors


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