RocketChat/Rocket.Chat · error · Meteor.Error

error-invalid-user

error-invalid-user

Error message

Invalid user to unmute

What it means

Thrown by `unmuteUserInRoom` when the subscription lookup succeeded but `Users.findOneByUsernameIgnoringCase(data.username)` returned no user (or a user document without a username). It means the room membership record exists while the corresponding user record does not — a data inconsistency such as a deleted user whose subscription lingered, or a username with no matching user document at all.

Source

Thrown at apps/meteor/server/meteor-methods/rooms/unmuteUserInRoom.ts:53

		throw new Meteor.Error('error-invalid-room-type', `${room.t} is not a valid room type`, {
			method: 'unmuteUserInRoom',
			type: room.t,
		});
	}

	const subscription = await Subscriptions.findOneByRoomIdAndUsername(data.rid, data.username, {
		projection: { _id: 1 },
	});

	if (!subscription) {
		throw new Meteor.Error('error-user-not-in-room', 'User is not in this room', {
			method: 'unmuteUserInRoom',
		});
	}

	const unmutedUser = await Users.findOneByUsernameIgnoringCase(data.username);
	if (!unmutedUser?.username) {
		throw new Meteor.Error('error-invalid-user', 'Invalid user to unmute', {
			method: 'unmuteUserInRoom',
		});
	}

	const fromUser = await Users.findOneById(fromId);
	if (!fromUser) {
		throw new Meteor.Error('error-invalid-user', 'Invalid user', {
			method: 'unmuteUserInRoom',
		});
	}

	await callbacks.run('beforeUnmuteUser', { unmutedUser, fromUser }, room);

	if (room.ro) {
		await Rooms.unmuteReadOnlyUsernameByRoomId(data.rid, unmutedUser.username);
	} else {
		await Rooms.unmuteMutedUsernameByRoomId(data.rid, unmutedUser.username);
	}

View on GitHub (pinned to b2c16d5842)

Solutions

  1. Confirm the user exists first, e.g. `GET /api/v1/users.info?username=<username>`, before calling the method.
  2. If the user was deleted, remove the orphan subscription from the room instead of unmuting (membership cleanup).
  3. Resolve the username from the subscription record (`sub.u.username`) so renames/casing cannot diverge.
  4. Audit for orphan subscriptions (`Subscriptions` entries whose `u._id` has no `users` document) and clean them up.

Example fix

// before
Meteor.call('unmuteUserInRoom', { rid, username });

// after - confirm the user document exists first (REST)
const res = await fetch(`/api/v1/users.info?username=${encodeURIComponent(username)}`, {
  headers: { 'X-Auth-Token': token, 'X-User-Id': uid },
});
if (!res.ok) {
  // user record gone: clean up the orphan subscription instead of unmuting
  return;
}
Meteor.call('unmuteUserInRoom', { rid, username });
Defensive patterns

Strategy: validation

Validate before calling

// verify both membership AND user existence before unmuting
const sub = await Subscriptions.findOneByRoomIdAndUsername(rid, username);
const user = sub && await Users.findOneByUsernameIgnoringCase(username);
if (sub && user?.username) {
  await Meteor.callAsync('unmuteUserInRoom', { rid, username: user.username });
}

Type guard

const hasUserRecord = async (username: string): Promise<boolean> =>
  Boolean(await Users.findOneByUsernameIgnoringCase(username));

Try / catch

try {
  await Meteor.callAsync('unmuteUserInRoom', { rid, username });
} catch (e: any) {
  if (e?.error === 'error-invalid-user' && e?.reason === 'Invalid user to unmute') {
    // user document missing: clean up the orphan subscription instead of retrying
  }
}

Prevention

When it happens

Trigger: Calling `unmuteUserInRoom` with a username whose subscription exists but whose user was deleted (user removed while muted, leaving an orphan subscription), or with a username that happens to match a subscription but has no user record (e.g. after a rename the old subscription key was kept).

Common situations: Partial user deletion that left subscriptions behind; workspaces imported or restored inconsistently; test fixtures that create subscriptions without matching users; automated scripts unmuting by username against stale data.

Understand the failure class

Background: "User not found", "Invalid user", and "does not exist": what missing-user lookup errors mean across Rocket.Chat, LiteLLM, Phabricator, rustfs, and pnpm — this error's family across 10 libraries.

Related errors


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