RocketChat/Rocket.Chat · error · Meteor.Error

error-invalid-user

error-invalid-user

Error message

Invalid user

What it means

Thrown by addRoomOwner() in apps/meteor/server/meteor-methods/rooms/addRoomOwner.ts:50 when Users.findOneById(userId) returns null or the found user has no username. Rocket.Chat identifies role targets by username for system messages and subscription lookups, so a user document without a username cannot receive the 'owner' role through this path.

Source

Thrown at apps/meteor/server/meteor-methods/rooms/addRoomOwner.ts:50

		});
	}

	const isFederated = isRoomFederated(room);

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

	if (isFederated && !isFederationEnabled()) {
		throw new FederationMatrixInvalidConfigurationError('unable to change room owners');
	}

	const user = await Users.findOneById(userId);

	if (!user?.username) {
		throw new Meteor.Error('error-invalid-user', 'Invalid user', {
			method: 'addRoomOwner',
		});
	}

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

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

	if (subscription.roles && Array.isArray(subscription.roles) === true && subscription.roles.includes('owner') === true) {
		throw new Meteor.Error('error-user-already-owner', 'User is already an owner', {
			method: 'addRoomOwner',
		});
	}

View on GitHub (pinned to b2c16d5842)

Solutions

  1. Confirm the user exists and has a username: await Users.findOneById(userId, { projection: { username: 1 } }).
  2. Fix the account data: set the username via the admin UI (Users > edit > username) or the REST user update endpoint, then retry.
  3. Re-fetch the userId at call time from a username lookup (Users.findOneByUsernameIgnoringCase) instead of caching IDs.
  4. If the user was deleted, choose another target or restore the account.

Example fix

// before
await addRoomOwner(uid, rid, maybeDeletedUserId);

// after
const target = await Users.findOneById(userId, { projection: { username: 1 } });
if (!target?.username) throw new Error('target user missing or has no username');
await addRoomOwner(uid, rid, target._id);
Defensive patterns

Strategy: validation

Validate before calling

const target = await Users.findOneById(userId, { projection: { username: 1 } });
if (!target?.username) throw new Error('target user missing or has no username');

Type guard

const hasUsername = (u: { username?: string } | null): u is { username: string } =>
  Boolean(u && typeof u.username === 'string' && u.username.length > 0);

Try / catch

try {
  await addRoomOwner(uid, rid, userId);
} catch (e) {
  if (e instanceof Meteor.Error && e.error === 'error-invalid-user') {
    // target userId wrong or account has no username; verify account data
  }
}

Prevention

When it happens

Trigger: Passing a userId that does not exist (deleted user, typo'd ID, ID from another workspace); targeting a user whose username field is unset — typically incompletely provisioned accounts, users mid-deletion, or app/bot users created without a username.

Common situations: Inviting an owner by an ID cached from before the user was removed; user import pipelines that leave username null; LDAP/CAS provisioning that created the document but failed before setting username; passing a subscription _id instead of a user _id.

Related errors


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