{"record":{"id":"c8d42947a2325f0c","repo":"RocketChat/Rocket.Chat","slug":"error-action-not-allowed-c8d429","errorCode":"error-action-not-allowed","errorMessage":"Deleting the rocket.cat user is not allowed","messagePattern":"Deleting the rocket\\.cat user is not allowed","errorType":"exception","errorClass":"Meteor.Error","httpStatus":null,"severity":"error","filePath":"apps/meteor/server/lib/users/deleteUser.ts","lineNumber":36,"sourceCode":"\nimport { getUserSingleOwnedRooms } from './getUserSingleOwnedRooms';\nimport { settings } from '../../settings';\nimport { callbacks } from '../callbacks';\nimport { i18n } from '../i18n';\nimport { FileUpload } from '../media/file-upload';\nimport {\n\tnotifyOnRoomChangedById,\n\tnotifyOnIntegrationChangedByUserId,\n\tnotifyOnLivechatDepartmentAgentChanged,\n\tnotifyOnUserChange,\n} from '../notifyListener';\nimport { getSubscribedRoomsForUserWithDetails, shouldRemoveOrChangeOwner } from '../rooms/getRoomsWithSingleOwner';\nimport { relinquishRoomOwnerships } from '../rooms/relinquishRoomOwnerships';\nimport { updateGroupDMsName } from '../rooms/updateGroupDMsName';\n\nexport async function deleteUser(userId: string, confirmRelinquish = false, deletedBy?: IUser['_id']): Promise<{ deletedRooms: string[] }> {\n\tif (userId === 'rocket.cat') {\n\t\tthrow new Meteor.Error('error-action-not-allowed', 'Deleting the rocket.cat user is not allowed', {\n\t\t\tmethod: 'deleteUser',\n\t\t\taction: 'Delete_user',\n\t\t});\n\t}\n\n\tconst user = await Users.findOneById(userId, {\n\t\tprojection: { username: 1, avatarOrigin: 1, roles: 1, federated: 1 },\n\t});\n\n\tif (!user) {\n\t\treturn { deletedRooms: [] };\n\t}\n\n\tif (isUserFederated(user)) {\n\t\tthrow new Meteor.Error('error-not-allowed', 'User participated in federation, this user can only be deactivated permanently', {\n\t\t\tmethod: 'deleteUser',\n\t\t});\n\t}","sourceCodeStart":18,"sourceCodeEnd":54,"githubUrl":"https://github.com/RocketChat/Rocket.Chat/blob/b2c16d5842cbe6b69b59bdf6fc5e5f1afcd1f0b0/apps/meteor/server/lib/users/deleteUser.ts#L18-L54","documentation":"deleteUser throws error-action-not-allowed (method 'deleteUser', action 'Delete_user') when the target id is exactly 'rocket.cat', the built-in bot user. This is a hard-coded protection: the internal bot cannot be deleted because system messages and integrations depend on it.","triggerScenarios":"Admin UI 'delete user' on the rocket.cat account, or REST/programmatic deletion with userId 'rocket.cat'; mass-deletion scripts iterating over all user ids without excluding it.","commonSituations":"Cleanup scripts that enumerate users and try to remove everything; automated tests creating/deleting users that accidentally include the bot's fixed id.","solutions":["Exclude 'rocket.cat' from any bulk deletion logic","If the bot is unwanted, disable it via settings or remove the bot flag instead of deleting the user","Guard the delete call: if (userId === 'rocket.cat') skip"],"exampleFix":"// before\nfor (const uid of allUserIds) {\n  await deleteUser(uid);\n}\n\n// after\nfor (const uid of allUserIds) {\n  if (uid === 'rocket.cat') continue;\n  await deleteUser(uid);\n}","handlingStrategy":"validation","validationCode":"if (userId === 'rocket.cat') {\n  throw new Error('The rocket.cat bot cannot be deleted');\n}\nawait deleteUser(userId, confirmRelinquish);","typeGuard":"const isProtectedUserId = (id: string): boolean => id === 'rocket.cat';","tryCatchPattern":"try {\n  await deleteUser(userId);\n} catch (e) {\n  if (isMeteorErrorCode(e, 'error-action-not-allowed') && userId === 'rocket.cat') {\n  \tskipProtectedAccount();\n  }\n}","preventionTips":["Exclude 'rocket.cat' from bulk deletions and offboarding scripts","Disable the bot via settings rather than deletion"],"tags":["users","deletion","bot","protected-account"],"backgroundTag":"protected-account","analyzedSha":"b2c16d5842cbe6b69b59bdf6fc5e5f1afcd1f0b0","analyzedAt":"2026-08-18T15:26:39.429Z","contentChangedAt":"2026-08-18T15:26:39.429Z","schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}