{"record":{"id":"ab91284b3080b90d","repo":"RocketChat/Rocket.Chat","slug":"error-invalid-user-ab9128","errorCode":"error-invalid-user","errorMessage":"Invalid user","messagePattern":"Invalid user","errorType":"exception","errorClass":"MeteorError","httpStatus":null,"severity":"error","filePath":"apps/meteor/server/lib/roles/removeUserFromRoles.ts","lineNumber":16,"sourceCode":"import { MeteorError } from '@rocket.chat/core-services';\nimport type { IRole, IUser, IRoom } from '@rocket.chat/core-typings';\nimport { Users, Subscriptions, Roles } from '@rocket.chat/models';\n\nimport { syncRoomRolePriorityForUserAndRoom } from './syncRoomRolePriority';\nimport { validateRoleList } from './validateRoleList';\nimport { notifyOnSubscriptionChangedByRoomIdAndUserId } from '../notifyListener';\n\nexport const removeUserFromRolesAsync = async (userId: IUser['_id'], roles: IRole['_id'][], scope?: IRoom['_id']): Promise<boolean> => {\n\tif (!userId || !roles) {\n\t\treturn false;\n\t}\n\n\tconst user = await Users.findOneById(userId, { projection: { _id: 1 } });\n\tif (!user) {\n\t\tthrow new MeteorError('error-invalid-user', 'Invalid user');\n\t}\n\n\tif (!(await validateRoleList(roles))) {\n\t\tthrow new MeteorError('error-invalid-role', 'Invalid role');\n\t}\n\n\tif (process.env.NODE_ENV === 'development' && (scope === 'Users' || scope === 'Subscriptions')) {\n\t\tthrow new Error('Roles.removeUserRoles method received a role scope instead of a scope value.');\n\t}\n\n\tfor await (const roleId of roles) {\n\t\tconst role = await Roles.findOneById<Pick<IRole, '_id' | 'scope'>>(roleId, { projection: { scope: 1 } });\n\t\tif (!role) {\n\t\t\tcontinue;\n\t\t}\n\n\t\tif (role.scope === 'Subscriptions' && scope) {\n\t\t\tconst removeRolesResponse = await Subscriptions.removeRolesByUserId(userId, [roleId], scope);","sourceCodeStart":1,"sourceCodeEnd":34,"githubUrl":"https://github.com/RocketChat/Rocket.Chat/blob/b2c16d5842cbe6b69b59bdf6fc5e5f1afcd1f0b0/apps/meteor/server/lib/roles/removeUserFromRoles.ts#L1-L34","documentation":"MeteorError('error-invalid-user', 'Invalid user') thrown by removeUserFromRolesAsync when the userId has no matching user document. The existence check runs before role validation, so a bad user id fails even if the roles are valid.","triggerScenarios":"Removing roles from a user id that was deleted or never existed: stale job payloads, scripts, or retried API requests after user deletion.","commonSituations":"User deleted while a role-cleanup job was queued; imported data with dangling user references; retrying an old moderation action.","solutions":["Look the user up (Users.findOneById / users.info API) and drop or fix the work item.","Treat removal for a deleted user as a skip, not a batch failure.","Re-sync automation user lists to remove stale ids."],"exampleFix":"// before\nawait removeUserFromRolesAsync(userId, ['bot']); // throws error-invalid-user\n\n// after\nconst user = await Users.findOneById(userId, { projection: { _id: 1 } });\nif (user) {\n  await removeUserFromRolesAsync(userId, ['bot']);\n}","handlingStrategy":"validation","validationCode":"const user = await Users.findOneById(userId, { projection: { _id: 1 } });\nif (!user) {\n  // nothing to de-role: skip instead of failing the batch\n} else {\n  await removeUserFromRolesAsync(userId, roles, scope);\n}","typeGuard":null,"tryCatchPattern":"try {\n  await removeUserFromRolesAsync(userId, roles, scope);\n} catch (error: any) {\n  if (error?.error === 'error-invalid-user') {\n    // user deleted: drop the work item and continue\n  }\n}","preventionTips":["Filter deleted users out of role-cleanup batches.","Handle 'error-invalid-user' as a skip, not a batch failure.","Re-sync automation user lists after deletions."],"tags":["users","roles","validation"],"backgroundTag":"user-not-found","analyzedSha":"b2c16d5842cbe6b69b59bdf6fc5e5f1afcd1f0b0","analyzedAt":"2026-08-18T15:26:39.429Z","schemaVersion":2},"datasetVersion":"2026-08-21T13:17:26.733Z"}