RocketChat/Rocket.Chat · error · Meteor.Error

error-user-not-found

error-user-not-found

Error message

User not found

What it means

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.

Source

Thrown at apps/meteor/server/meteor-methods/rooms/addUsersToRoom.ts:94

		});
	}

	// Missing the users to be added
	if (!Array.isArray(data.users)) {
		throw new Meteor.Error('error-invalid-arguments', 'Invalid arguments', {
			method: 'addUsersToRoom',
		});
	}

	await beforeAddUsersToRoom.run({ usernames: data.users, inviter: user }, room);

	await Promise.all(
		data.users.map(async (username) => {
			const sanitizedUsername = sanitizeUsername(username);

			const newUser = await Users.findOneByUsernameIgnoringCase(sanitizedUsername);
			if (!newUser) {
				throw new Meteor.Error('error-user-not-found', 'User not found', {
					method: 'addUsersToRoom',
				});
			}

			const subscription = await Subscriptions.findOneByRoomIdAndUserId(data.rid, newUser._id);
			if (subscription && isBannedSubscription(subscription)) {
				throw new Meteor.Error('error-user-is-banned', 'User is banned from this room', {
					method: 'addUsersToRoom',
				});
			}
			if (!subscription) {
				return addUserToRoom(data.rid, newUser, user);
			}
			if (!newUser.username) {
				return;
			}
			void api.broadcast('notify.ephemeralMessage', userId, data.rid, {
				msg: i18n.t('Username_is_already_in_here', {

View on GitHub (pinned to b2c16d5842)

Solutions

  1. 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).
  2. Send the exact username (not display name/email); strip leading '@' — the sanitizer handles '@name' but not every variation.
  3. If users come from an external source, wait for/verify provisioning (SCIM/LDAP import) before inviting.
  4. For federated targets, verify the full user@domain:server form and that federation is enabled, otherwise invite the local account name.

Example fix

// before
await addUsersToRoomMethod(uid, { rid, users: ['alice', 'bob-typo'] }); // whole batch fails

// after
const users = (
  await Promise.all(
    raw.map(async (name) => {
      const u = await Users.findOneByUsernameIgnoringCase(sanitizeUsername(name), { projection: { username: 1 } });
      return u?.username;
    }),
  )
).filter(Boolean) as string[];
await addUsersToRoomMethod(uid, { rid, users });
Defensive patterns

Strategy: validation

Validate before calling

const found = await Users.findOneByUsernameIgnoringCase(sanitizeUsername(name), { projection: { username: 1 } });
if (!found?.username) continue; // collect unknown names and report instead of aborting the batch

Type guard

const isKnownUsername = async (name: string): Promise<boolean> =>
  Boolean(await Users.findOneByUsernameIgnoringCase(sanitizeUsername(name), { projection: { _id: 1 } }));

Try / catch

try {
  await addUsersToRoomMethod(uid, { rid, users });
} catch (e) {
  if (e instanceof Meteor.Error && e.error === 'error-user-not-found') {
    // resolve each username first; invite the subset that exists and report the rest
  }
}

Prevention

When it happens

Trigger: 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.

Common situations: 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.

Related errors


AI-assisted analysis of RocketChat/Rocket.Chat@b2c16d5842 (2026-08-18). Data as JSON: /api/errors/5127e3895c4cc616. Report an issue: GitHub.