{"record":{"id":"02c3e36ec2a4b11b","repo":"RocketChat/Rocket.Chat","slug":"error-admin-required","errorCode":"error-admin-required","errorMessage":"You need to have at least one admin","messagePattern":"You need to have at least one admin","errorType":"exception","errorClass":"Meteor.Error","httpStatus":null,"severity":"error","filePath":"apps/meteor/server/api/v1/roles.ts","lineNumber":303,"sourceCode":"\n\t\t\tif (!user) {\n\t\t\t\tthrow new Meteor.Error('error-invalid-user', 'There is no user with this username');\n\t\t\t}\n\n\t\t\tconst role = await Roles.findOneById(roleId);\n\n\t\t\tif (!role) {\n\t\t\t\tthrow new Meteor.Error('error-invalid-roleId', 'This role does not exist');\n\t\t\t}\n\n\t\t\tif (!(await hasAnyRoleAsync(user._id, [role._id], scope))) {\n\t\t\t\tthrow new Meteor.Error('error-user-not-in-role', 'User is not in this role');\n\t\t\t}\n\n\t\t\tif (role._id === 'admin') {\n\t\t\t\tconst adminCount = await Roles.countUsersInRole('admin');\n\t\t\t\tif (adminCount === 1) {\n\t\t\t\t\tthrow new Meteor.Error('error-admin-required', 'You need to have at least one admin');\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tawait removeUserFromRolesAsync(user._id, [role._id], scope);\n\n\t\t\tif (settings.get('UI_DisplayRoles')) {\n\t\t\t\tvoid api.broadcast('user.roleUpdate', {\n\t\t\t\t\ttype: 'removed',\n\t\t\t\t\t_id: role._id,\n\t\t\t\t\tu: {\n\t\t\t\t\t\t_id: user._id,\n\t\t\t\t\t\tusername: user.username,\n\t\t\t\t\t},\n\t\t\t\t\tscope,\n\t\t\t\t});\n\t\t\t}\n\n\t\t\treturn API.v1.success({","sourceCodeStart":285,"sourceCodeEnd":321,"githubUrl":"https://github.com/RocketChat/Rocket.Chat/blob/f9d3ec372bb580fa8d036f94cf03925a478ef768/apps/meteor/server/api/v1/roles.ts#L285-L321","documentation":"Thrown by POST roles.removeUserFromRole when role._id === 'admin', adminCount === 1, and the operation would remove the last admin. This is a safety guard preventing lockout. Returns a structured Meteor.Error('error-admin-required', 'You need to have at least one admin').","triggerScenarios":"POST /api/v1/roles.removeUserFromRole with roleId 'admin' (or the admin role _id) for the only remaining administrator, globally.","commonSituations":"Demoting/removing the sole admin account; cleanup script strips all admin grants; removing a user who is the last admin before promoting another.","solutions":["Promote at least one other user to admin first via roles.addUserToRole, then retry the removal.","If the intent is to change the admin account, grant admin to the new user before revoking the old one.","In automation, check adminCount via roles.getUsersInRole?role=admin and guard against count <= 1."],"exampleFix":"// before\nawait fetch('/api/v1/roles.removeUserFromRole', { method:'POST', body: JSON.stringify({ roleId: 'admin', username }) });\n\n// after - ensure a second admin exists first\nconst { total } = await fetch('/api/v1/roles.getUsersInRole?role=admin').then(r=>r.json());\nif (total <= 1) {\n  await fetch('/api/v1/roles.addUserToRole', { method:'POST', body: JSON.stringify({ roleId:'admin', username: successor }) });\n}\nawait fetch('/api/v1/roles.removeUserFromRole', { method:'POST', body: JSON.stringify({ roleId:'admin', username }) });","handlingStrategy":"validation","validationCode":"// Never remove the last admin: ensure >= 2 admins first\nconst { total } = await fetch('/api/v1/roles.getUsersInRole?role=admin').then(r => r.json());\nif (total <= 1) {\n  await fetch('/api/v1/roles.addUserToRole', { method:'POST', body: JSON.stringify({ roleId:'admin', username: successor }) });\n}\nawait fetch('/api/v1/roles.removeUserFromRole', { method:'POST', body: JSON.stringify({ roleId:'admin', username }) });","typeGuard":null,"tryCatchPattern":"try {\n  await fetch('/api/v1/roles.removeUserFromRole', {method:'POST',body:JSON.stringify({roleId:'admin',username})}).then(r=>r.json());\n} catch (e) {\n  if (e.error === 'error-admin-required') { /* promote another admin, then retry */ }\n}","preventionTips":["Promote a successor admin before demoting the current one.","In automation, assert adminCount > 1 before any admin removal."],"tags":["roles","rest-api","admin","safety-guard","business-rule"],"backgroundTag":null,"analyzedSha":"f9d3ec372bb580fa8d036f94cf03925a478ef768","analyzedAt":"2026-08-12T19:07:17.372Z","schemaVersion":2},"datasetVersion":"2026-08-12T23:17:12.415Z"}