{"record":{"id":"17fdc55fac53766f","repo":"RocketChat/Rocket.Chat","slug":"error-action-not-allowed-17fdc5","errorCode":"error-action-not-allowed","errorMessage":"Leaving the app without admins is not allowed","messagePattern":"Leaving the app without admins is not allowed","errorType":"exception","errorClass":"Meteor.Error","httpStatus":null,"severity":"error","filePath":"apps/meteor/server/meteor-methods/users/deleteUser.ts","lineNumber":37,"sourceCode":"\tconst user = await Users.findOneById(userId);\n\tif (!user) {\n\t\tthrow new Meteor.Error('error-invalid-user', 'Invalid user to delete', {\n\t\t\tmethod: 'deleteUser',\n\t\t});\n\t}\n\n\tif (user.type === 'app') {\n\t\tthrow new Meteor.Error('error-cannot-delete-app-user', 'Deleting app user is not allowed', {\n\t\t\tmethod: 'deleteUser',\n\t\t});\n\t}\n\n\tconst adminCount = await Users.countDocuments({ roles: 'admin' });\n\n\tconst userIsAdmin = user.roles?.indexOf('admin') > -1;\n\n\tif (adminCount === 1 && userIsAdmin) {\n\t\tthrow new Meteor.Error('error-action-not-allowed', 'Leaving the app without admins is not allowed', {\n\t\t\tmethod: 'deleteUser',\n\t\t\taction: 'Remove_last_admin',\n\t\t});\n\t}\n\n\tawait deleteUser(userId, confirmRelinquish, fromUserId);\n\n\treturn true;\n};\n\nMeteor.methods<ServerMethods>({\n\tasync deleteUser(userId, confirmRelinquish = false) {\n\t\tmethodDeprecationLogger.method('deleteUser', '9.0.0', '/v1/users.delete');\n\t\tcheck(userId, String);\n\n\t\tconst uid = Meteor.userId();\n\t\tif (!uid) {\n\t\t\tthrow new Meteor.Error('error-not-allowed', 'Not allowed', {","sourceCodeStart":19,"sourceCodeEnd":55,"githubUrl":"https://github.com/RocketChat/Rocket.Chat/blob/b2c16d5842cbe6b69b59bdf6fc5e5f1afcd1f0b0/apps/meteor/server/meteor-methods/users/deleteUser.ts#L19-L55","documentation":"`executeDeleteUser` counts users with the `admin` role (`Users.countDocuments({ roles: 'admin' })`) and refuses the deletion when the count is exactly 1 and the target user is that admin. This is the last-admin protection: without it a workspace could be left with no administrator able to manage it. The thrown details include `action: 'Remove_last_admin'`.","triggerScenarios":"Calling `deleteUser` (or REST `users.delete`) on the only remaining admin — e.g. cleaning up old admin accounts without first transferring rights, or deleting the seed admin after setup while no second admin exists.","commonSituations":"Offboarding scripts removing the original admin; downsizing from several admins to one and deleting in the wrong order; fresh installs experimenting with the initial admin account; self-managed servers recovered with a single admin left.","solutions":["Promote another user to admin first (Admin → Users → Make Admin), then delete the original.","Before deleting any admin, check the admin count and skip/abort when it is 1.","In automation, order deletions so at least one admin always remains, or create a break-glass admin beforehand.","If you are locked out conceptually, use the workspace owner/registration account or CLI to grant a new admin."],"exampleFix":"// before - deletes even when target is the last admin\nawait deleteUserFn(uid, targetUserId);\n\n// after - guard the last-admin case client/server side\nconst admins = users.filter((u) => u.roles?.includes('admin'));\nif (admins.length === 1 && admins[0]._id === targetUserId) {\n  throw new Error('Promote another admin before deleting the last one');\n}\nawait deleteUserFn(uid, targetUserId);","handlingStrategy":"validation","validationCode":"// abort before deleting the last remaining admin\nconst adminCount = await Users.countDocuments({ roles: 'admin' });\nconst targetIsAdmin = (await Users.findOneById(userId))?.roles?.includes('admin');\nif (adminCount === 1 && targetIsAdmin) {\n  throw new Error('Promote another admin before deleting the last one');\n}\nawait deleteUserFn(uid, userId);","typeGuard":"const wouldLeaveNoAdmin = (adminIds: string[], targetUserId: string): boolean => adminIds.length === 1 && adminIds[0] === targetUserId;","tryCatchPattern":"try {\n  await Meteor.callAsync('deleteUser', userId);\n} catch (e: any) {\n  if (e?.error === 'error-action-not-allowed' && e?.details?.action === 'Remove_last_admin') {\n    // promote a second admin first, then retry the deletion\n  }\n}","preventionTips":["Always keep at least two admins (or a break-glass admin) before offboarding any admin.","Order bulk admin deletions so the last admin is never the deletion target.","Check the details.action === 'Remove_last_admin' discriminator when handling this error."],"tags":["meteor","users","delete","admin","safety-guard"],"backgroundTag":"last-admin-protection","analyzedSha":"b2c16d5842cbe6b69b59bdf6fc5e5f1afcd1f0b0","analyzedAt":"2026-08-18T15:26:39.429Z","schemaVersion":2},"datasetVersion":"2026-08-21T13:17:26.733Z"}