{"record":{"id":"f5a2f8b144ad112c","repo":"RocketChat/Rocket.Chat","slug":"user-not-found-f5a2f8","errorCode":"user-not-found","errorMessage":"user-not-found","messagePattern":"user-not-found","errorType":"exception","errorClass":"Meteor.Error","httpStatus":null,"severity":"error","filePath":"apps/meteor/server/lib/rooms/addUserToRoom.ts","lineNumber":48,"sourceCode":"\t\tskipSystemMessage?: boolean;\n\t\tskipAlertSound?: boolean;\n\t\tcreateAsHidden?: boolean;\n\t} = {},\n): Promise<boolean | undefined> => {\n\tconst now = new Date();\n\tconst room = await Rooms.findOneById(rid);\n\n\tif (!room) {\n\t\tthrow new Meteor.Error('error-invalid-room', 'Invalid room', {\n\t\t\tmethod: 'addUserToRoom',\n\t\t});\n\t}\n\n\tconst userToBeAdded = await Users.findOneById(user._id);\n\tconst roomDirectives = roomCoordinator.getRoomDirectives(room.t);\n\n\tif (!userToBeAdded) {\n\t\tthrow new Meteor.Error('user-not-found');\n\t}\n\n\tif (\n\t\t!(await roomDirectives.allowMemberAction(room, RoomMemberActions.JOIN, userToBeAdded._id)) &&\n\t\t!(await roomDirectives.allowMemberAction(room, RoomMemberActions.INVITE, userToBeAdded._id))\n\t) {\n\t\treturn;\n\t}\n\n\ttry {\n\t\tconst inviterUser = inviter && ((await Users.findOneById(inviter._id)) || undefined);\n\t\t// Not \"duplicated\": we're moving away from callbacks so this is a patch function. We should migrate the next one to be a patch or use this same patch, instead of calling both\n\t\tawait beforeAddUserToRoomPatch([userToBeAdded.username!], room, inviterUser);\n\t\tawait beforeAddUserToRoom.run({ user: userToBeAdded, inviter: inviterUser }, room);\n\t} catch (error) {\n\t\tthrow new Meteor.Error((error as any)?.message);\n\t}\n","sourceCodeStart":30,"sourceCodeEnd":66,"githubUrl":"https://github.com/RocketChat/Rocket.Chat/blob/b2c16d5842cbe6b69b59bdf6fc5e5f1afcd1f0b0/apps/meteor/server/lib/rooms/addUserToRoom.ts#L30-L66","documentation":"Meteor.Error('user-not-found') thrown by addUserToRoom when Users.findOneById(user._id) returns nothing: the user being added no longer exists. Note the unconventional code (no 'error-' prefix) and the empty message.","triggerScenarios":"Adding a deleted user to a room: stale member picker, user deleted between selection and submission, bulk-add lists with stale ids.","commonSituations":"Deleted users still shown in an outdated user picker; import scripts referencing missing users; races with user deletion.","solutions":["Confirm the user exists (users.info API / Users.findOneById) before adding.","Refresh the user picker or member cache.","Filter deleted users out of bulk add lists."],"exampleFix":"// before\nawait addUserToRoom(rid, user); // throws 'user-not-found'\n\n// after\nconst exists = await Users.findOneById(user._id, { projection: { _id: 1 } });\nif (exists) {\n  await addUserToRoom(rid, user);\n}","handlingStrategy":"validation","validationCode":"const exists = await Users.findOneById(user._id, { projection: { _id: 1 } });\nif (!exists) {\n  // skip adding a deleted user\n}","typeGuard":null,"tryCatchPattern":"try {\n  await addUserToRoom(rid, user, inviter);\n} catch (error: any) {\n  if (error?.error === 'user-not-found') {\n    // filter this user out of the member list and continue\n  }\n}","preventionTips":["Filter deleted users from member pickers and bulk imports.","Note the code has no 'error-' prefix - match on 'user-not-found' exactly.","Refresh user data before bulk membership operations."],"tags":["users","rooms","validation"],"backgroundTag":"user-not-found","analyzedSha":"b2c16d5842cbe6b69b59bdf6fc5e5f1afcd1f0b0","analyzedAt":"2026-08-18T15:26:39.429Z","schemaVersion":2},"datasetVersion":"2026-08-21T13:17:26.733Z"}