RocketChat/Rocket.Chat · warning · Meteor.Error

error-empty-invite-list

error-empty-invite-list

Error message

Cannot invite if no valid users are provided

What it means

Thrown by groups.invite (groups.ts:868-872) in the non-federated branch. getUserListFromParams resolves userId/username/user/userIds/usernames to local user documents; if the resulting list is empty, none of the supplied identifiers matched a local user. (Note: getUserListFromParams itself throws error-users-params-not-provided when no user param is sent at all, so reaching this empty-list check means at least one identifier was supplied but none resolved.) Federated rooms take a different branch (getUsernameListFromParams) and never reach this throw.

Source

Thrown at apps/meteor/server/api/v1/groups.ts:871

		const groupRoom = await Rooms.findOneByIdOrName(idOrName);
		const { _id: rid, t: type } = groupRoom || {};

		if (!rid || type !== 'p') {
			throw new Meteor.Error('error-room-not-found', 'The required "roomId" or "roomName" param provided does not match any group');
		}

		// Federated rooms invite by raw username: the federated user record is created
		// lazily inside addUsersToRoomMethod, so we must not require it to exist locally yet.
		if (groupRoom && isRoomNativeFederated(groupRoom)) {
			const usernames = await getUsernameListFromParams(this.bodyParams);

			await addUsersToRoomMethod(this.userId, { rid, users: usernames }, this.user);
		} else {
			const users = await getUserListFromParams(this.bodyParams);

			if (!users.length) {
				throw new Meteor.Error('error-empty-invite-list', 'Cannot invite if no valid users are provided');
			}

			await addUsersToRoomMethod(this.userId, { rid, users: users.map((u) => u.username).filter(isTruthy) }, this.user);
		}

		const room = await Rooms.findOneById(rid, { projection: API.v1.defaultFieldsToExclude });

		if (!room) {
			throw new Meteor.Error('error-room-not-found', 'The required "roomId" or "roomName" param provided does not match any group');
		}

		return API.v1.success({
			group: await composeRoomWithLastMessage(room, this.userId),
		});
	},
);

API.v1.post(

View on GitHub (pinned to f9d3ec372b)

Solutions

  1. Resolve each user identifier to a local user first (e.g. via users.info) and drop unknowns before calling invite.
  2. Confirm you are inviting existing local users; for cross-workspace invites, enable federation and use the federated username format (user@server).
  3. Supply userIds/usernames exactly as they appear in the workspace directory.
  4. If the group is meant to be federated, verify isRoomNativeFederated is true so the invite takes the username-passthrough branch.

Example fix

// before
await POST('/api/v1/groups.invite', { roomId, usernames: ['alice', 'ghost'] }); // 'ghost' missing, 'alice' fine but list still non-empty -> would succeed; single bad invite fails

// after: pre-validate users exist locally
const valid = [];
for (const u of usernames) {
  const r = await GET('/api/v1/users.info', { username: u }).catch(() => null);
  if (r?.user) valid.push(u);
}
if (!valid.length) throw new Error('No matching users');
await POST('/api/v1/groups.invite', { roomId, usernames: valid });
Defensive patterns

Strategy: validation

Validate before calling

// Pre-flight: resolve every supplied user to a local account before inviting.
async function resolveLocalUsernames(api, usernames) {
  const out = [];
  for (const u of usernames) {
    const r = await api.get('/api/v1/users.info', { username: u }).catch(() => null);
    if (r?.user?.username) out.push(r.user.username);
  }
  return out;
}
const valid = await resolveLocalUsernames(api, usernames);
if (!valid.length) throw new Error('No matching local users to invite');
await api.post('/api/v1/groups.invite', { roomId, usernames: valid });

Type guard

function isLocalUserResolved(u) {
  return u != null && typeof u.username === 'string' && u.username.length > 0;
}

Try / catch

try {
  await api.post('/api/v1/groups.invite', { roomId, usernames });
} catch (e) {
  if (isMeteorError(e) && e.reason === 'error-empty-invite-list') {
    showFormError('None of the supplied users exist in this workspace');
    return;
  }
  throw e;
}

Prevention

When it happens

Trigger: POST groups.invite on a native (non-federated) private group where every supplied userId/username/user/userIds/usernames refers to a non-existent, deleted, or misspelled user. Also when usernames are correct but federation is disabled so they have no local record.

Common situations: Inviting by email instead of username. Inviting users from another workspace without federation. Typos in usernames. Inviting deactivated/deleted accounts.

Related errors


AI-assisted analysis of RocketChat/Rocket.Chat@f9d3ec372b (2026-08-12). Data as JSON: /api/errors/663a3ee3bdddf8ad. Report an issue: GitHub.