{"record":{"id":"5127e3895c4cc616","repo":"RocketChat/Rocket.Chat","slug":"error-user-not-found-5127e3","errorCode":"error-user-not-found","errorMessage":"User not found","messagePattern":"User not found","errorType":"error_code","errorClass":"Meteor.Error","httpStatus":null,"severity":"error","filePath":"apps/meteor/server/meteor-methods/rooms/addUsersToRoom.ts","lineNumber":94,"sourceCode":"\t\t});\n\t}\n\n\t// Missing the users to be added\n\tif (!Array.isArray(data.users)) {\n\t\tthrow new Meteor.Error('error-invalid-arguments', 'Invalid arguments', {\n\t\t\tmethod: 'addUsersToRoom',\n\t\t});\n\t}\n\n\tawait beforeAddUsersToRoom.run({ usernames: data.users, inviter: user }, room);\n\n\tawait Promise.all(\n\t\tdata.users.map(async (username) => {\n\t\t\tconst sanitizedUsername = sanitizeUsername(username);\n\n\t\t\tconst newUser = await Users.findOneByUsernameIgnoringCase(sanitizedUsername);\n\t\t\tif (!newUser) {\n\t\t\t\tthrow new Meteor.Error('error-user-not-found', 'User not found', {\n\t\t\t\t\tmethod: 'addUsersToRoom',\n\t\t\t\t});\n\t\t\t}\n\n\t\t\tconst subscription = await Subscriptions.findOneByRoomIdAndUserId(data.rid, newUser._id);\n\t\t\tif (subscription && isBannedSubscription(subscription)) {\n\t\t\t\tthrow new Meteor.Error('error-user-is-banned', 'User is banned from this room', {\n\t\t\t\t\tmethod: 'addUsersToRoom',\n\t\t\t\t});\n\t\t\t}\n\t\t\tif (!subscription) {\n\t\t\t\treturn addUserToRoom(data.rid, newUser, user);\n\t\t\t}\n\t\t\tif (!newUser.username) {\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tvoid api.broadcast('notify.ephemeralMessage', userId, data.rid, {\n\t\t\t\tmsg: i18n.t('Username_is_already_in_here', {","sourceCodeStart":76,"sourceCodeEnd":112,"githubUrl":"https://github.com/RocketChat/Rocket.Chat/blob/b2c16d5842cbe6b69b59bdf6fc5e5f1afcd1f0b0/apps/meteor/server/meteor-methods/rooms/addUsersToRoom.ts#L76-L112","documentation":"Thrown inside the per-user loop of addUsersToRoomMethod() (apps/meteor/server/meteor-methods/rooms/addUsersToRoom.ts:94) when Users.findOneByUsernameIgnoringCase(sanitizedUsername) returns null — no user matches the given username (after sanitizeUsername strips a leading '@' or keeps federated user@domain:server forms). Because the loop runs inside Promise.all over all requested usernames, one unknown username rejects the entire invitation batch.","triggerScenarios":"Inviting by a username with a typo; the account was deleted or renamed before the invite; inviting by display name or email instead of username; federated username with a malformed user@domain:server shape so it is looked up verbatim and misses; trailing whitespace or a masked/mentioned format the sanitizer does not normalize.","commonSituations":"Bots inviting from an external directory that is out of sync with Rocket.Chat users; user renames breaking stored lists; provisioning lag where the invite fires before the user import finished; mixing up username and name fields in spreadsheets.","solutions":["Resolve usernames ahead of time and drop unknown ones (or report them) so one bad entry does not abort the batch: const found = await Users.findOneByUsernameIgnoringCase(name).","Send the exact username (not display name/email); strip leading '@' — the sanitizer handles '@name' but not every variation.","If users come from an external source, wait for/verify provisioning (SCIM/LDAP import) before inviting.","For federated targets, verify the full user@domain:server form and that federation is enabled, otherwise invite the local account name."],"exampleFix":"// before\nawait addUsersToRoomMethod(uid, { rid, users: ['alice', 'bob-typo'] }); // whole batch fails\n\n// after\nconst users = (\n  await Promise.all(\n    raw.map(async (name) => {\n      const u = await Users.findOneByUsernameIgnoringCase(sanitizeUsername(name), { projection: { username: 1 } });\n      return u?.username;\n    }),\n  )\n).filter(Boolean) as string[];\nawait addUsersToRoomMethod(uid, { rid, users });","handlingStrategy":"validation","validationCode":"const found = await Users.findOneByUsernameIgnoringCase(sanitizeUsername(name), { projection: { username: 1 } });\nif (!found?.username) continue; // collect unknown names and report instead of aborting the batch","typeGuard":"const isKnownUsername = async (name: string): Promise<boolean> =>\n  Boolean(await Users.findOneByUsernameIgnoringCase(sanitizeUsername(name), { projection: { _id: 1 } }));","tryCatchPattern":"try {\n  await addUsersToRoomMethod(uid, { rid, users });\n} catch (e) {\n  if (e instanceof Meteor.Error && e.error === 'error-user-not-found') {\n    // resolve each username first; invite the subset that exists and report the rest\n  }\n}","preventionTips":["Pre-resolve usernames before bulk invites so one bad entry cannot reject the batch.","Use exact usernames (not display names/emails); strip leading '@'.","For external directories, sync/verify provisioning before inviting."],"tags":["meteor-method","users","username","validation","batch-failure"],"backgroundTag":"user-not-found","analyzedSha":"b2c16d5842cbe6b69b59bdf6fc5e5f1afcd1f0b0","analyzedAt":"2026-08-18T15:26:39.429Z","schemaVersion":2},"datasetVersion":"2026-08-21T13:17:26.733Z"}