RocketChat/Rocket.Chat · error · Meteor.Error

error-invalid-user

error-invalid-user

Error message

Invalid user

What it means

removeRoomOwner loads the target with Users.findOneById(userId) and requires a non-empty username; throws error-invalid-user when the target does not exist or has no username. The userId argument must be the user's _id — passing a username here will always fail this lookup.

Source

Thrown at apps/meteor/server/meteor-methods/rooms/removeRoomOwner.ts:41

	check(rid, String);
	check(userId, String);

	const room = await Rooms.findOneById(rid, { projection: { t: 1, federated: 1, federation: 1 } });
	if (!room) {
		throw new Meteor.Error('error-invalid-room', 'Invalid room', {
			method: 'removeRoomOwner',
		});
	}

	if (!(await hasPermissionAsync(fromUserId, 'set-owner', rid)) && !isRoomFederated(room)) {
		throw new Meteor.Error('error-not-allowed', 'Not allowed', {
			method: 'removeRoomOwner',
		});
	}

	const user = await Users.findOneById(userId);
	if (!user?.username) {
		throw new Meteor.Error('error-invalid-user', 'Invalid user', {
			method: 'removeRoomOwner',
		});
	}

	const subscription = await Subscriptions.findOneByRoomIdAndUserId(rid, user._id);

	if (!subscription) {
		throw new Meteor.Error('error-invalid-room', 'Invalid room', {
			method: 'removeRoomOwner',
		});
	}

	if (Array.isArray(subscription.roles) === false || subscription.roles?.includes('owner') === false) {
		throw new Meteor.Error('error-user-not-owner', 'User is not an owner', {
			method: 'removeRoomOwner',
		});
	}

View on GitHub (pinned to b2c16d5842)

Solutions

  1. Resolve the target's _id (Users.findOneByUsername, or GET /api/v1/users.info?username=) before calling
  2. Validate that the user exists and has a username before offering owner-removal actions
  3. Drop stale targets from pickers when lookup fails

Example fix

// before
await Meteor.callAsync('removeRoomOwner', rid, targetUsername);

// after
const user = Users.findOne({ username: targetUsername });
if (!user?._id) throw new Error('target missing');
await Meteor.callAsync('removeRoomOwner', rid, user._id);
Defensive patterns

Strategy: validation

Validate before calling

const target = Users.findOne({ _id: userId });
if (!target?.username) {
  // target missing: skip call and refresh pickers
}

Type guard

const isRemovableUser = (u: { _id?: string; username?: string } | null | undefined): u is { _id: string; username: string } =>
  Boolean(u?._id && u?.username);

Try / catch

try {
  await Meteor.callAsync('removeRoomOwner', rid, userId);
} catch (err) {
  if (err instanceof Meteor.Error && err.error === 'error-invalid-user') {
    // target vanished: refresh member data
  }
}

Prevention

When it happens

Trigger: Passing the target's username rather than _id as the second argument; target deleted before the call landed; user record without a username.

Common situations: Member-management UIs keyed by username; target account removed while an admin had the role dialog open.

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/d8789ebc64fd5197. Report an issue: GitHub.