{"record":{"id":"655b061f9c327e71","repo":"gravitational/teleport","slug":"failed-to-delete-a-role-that-is-still-in-use-by-an","errorCode":null,"errorMessage":"failed to delete a role that is still in use by an access list, check the system server logs for more details","messagePattern":"failed to delete a role that is still in use by an access list, check the system server logs for more details","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"lib/auth/access.go","lineNumber":108,"sourceCode":"\t\tMetadata: apievents.Metadata{\n\t\t\tType: events.RoleCreatedEvent,\n\t\t\tCode: events.RoleCreatedCode,\n\t\t},\n\t\tUserMetadata: authz.ClientUserMetadata(ctx),\n\t\tResourceMetadata: apievents.ResourceMetadata{\n\t\t\tName: role.GetName(),\n\t\t},\n\t\tConnectionMetadata: authz.ConnectionMetadata(ctx),\n\t}); err != nil {\n\t\ta.logger.WarnContext(ctx, \"Failed to emit role create event.\", \"error\", err)\n\t}\n\treturn upserted, nil\n}\n\nvar (\n\terrDeleteRoleUser       = errors.New(\"failed to delete a role that is still in use by a user, check the system server logs for more details\")\n\terrDeleteRoleCA         = errors.New(\"failed to delete a role that is still in use by a certificate authority, check the system server logs for more details\")\n\terrDeleteRoleAccessList = errors.New(\"failed to delete a role that is still in use by an access list, check the system server logs for more details\")\n)\n\n// DeleteRole deletes a role and emits a related audit event.\nfunc (a *Server) DeleteRole(ctx context.Context, name string) error {\n\t// check if this role is used by CA or Users\n\tusers, err := a.Services.GetUsers(ctx, false)\n\tif err != nil {\n\t\treturn trace.Wrap(err)\n\t}\n\tfor _, u := range users {\n\t\tif slices.Contains(u.GetRoles(), name) {\n\t\t\t// Mask the actual error here as it could be used to enumerate users\n\t\t\t// within the system.\n\t\t\ta.logger.WarnContext(\n\t\t\t\tctx, \"Failed to delete role: role is still in use by a user\",\n\t\t\t\t\"role\", name, \"user\", u.GetName(),\n\t\t\t)\n\t\t\treturn trace.Wrap(errDeleteRoleUser)","sourceCodeStart":90,"sourceCodeEnd":126,"githubUrl":"https://github.com/gravitational/teleport/blob/1283425b60ec5f60d509ba4c791183d452923ff7/lib/auth/access.go#L90-L126","documentation":"DeleteRole refuses deletion when the role is used by an access list. errDeleteRoleAccessList is returned at two points (lib/auth/access.go:162 and :170) covering different access-list role positions (e.g. owner/grant roles and audit roles), with specifics logged server-side.","triggerScenarios":"Calling Server.DeleteRole(ctx, name) while any access list references the role as a member role, owner role, or audit role during the access-list scan.","commonSituations":"Cleanup of legacy roles while access-list automation still grants them; deleting a role that an access list uses for review/audit assignments; tenant onboarding scripts that create access lists pointing at soon-to-be-deleted roles.","solutions":["Check auth server logs to find which access list and which role position (member/owner/audit) references the role.","Update the access list (access_lists UpdateAccessList) to remove or replace the role reference, then retry DeleteRole.","If the access list itself is obsolete, delete the access list first, then the role."],"exampleFix":null,"handlingStrategy":"type-guard","validationCode":"lists, _ := accessLists.ListAccessLists(ctx)\nfor _, l := range lists { if usesRole(l, roleName) { return fmt.Errorf(\"role %q used by access list %q\", roleName, l.GetName()) } }","typeGuard":"if errors.Is(err, auth.ErrDeleteRoleAccessList) { /* role in use by an access list */ }","tryCatchPattern":"err := authServer.DeleteRole(ctx, roleName)\nif errors.Is(err, auth.ErrDeleteRoleAccessList) {\n    return trace.BadParameter(\"remove the role from all access lists (member/owner/audit) before deleting it\")\n}","preventionTips":["Enumerate access lists and check member, owner, and audit role fields before deleting a role.","Update access lists via UpdateAccessList to swap roles atomically before removal.","Centralize role cleanup scripts so they always process access lists alongside users and CAs."],"tags":["rbac","roles","access-lists","referential-integrity"],"backgroundTag":"resource-still-in-use","analyzedSha":"1283425b60ec5f60d509ba4c791183d452923ff7","analyzedAt":"2026-09-02T04:06:41.601Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-08T10:18:20.063Z"}