RocketChat/Rocket.Chat · error · Meteor.Error
error-invalid-user
error-invalid-user
Error message
Invalid user
What it means
After the permission check, addRoomLeader loads the target user with Users.findOneById(userId); if the document is missing or has no username, it throws error-invalid-user. A Rocket.Chat user without a username cannot receive a room role because the subscription lookup and the 'subscription-role-added' system message both key off username.
Source
Thrown at apps/meteor/server/meteor-methods/rooms/addRoomLeader.ts:34
interface ServerMethods {
addRoomLeader(rid: IRoom['_id'], userId: IUser['_id']): boolean;
}
}
export const addRoomLeader = async (fromUserId: IUser['_id'], rid: IRoom['_id'], userId: IUser['_id']): Promise<boolean> => {
check(rid, String);
check(userId, String);
if (!(await hasPermissionAsync(fromUserId, 'set-leader', rid))) {
throw new Meteor.Error('error-not-allowed', 'Not allowed', {
method: 'addRoomLeader',
});
}
const user = await Users.findOneById(userId);
if (!user?.username) {
throw new Meteor.Error('error-invalid-user', 'Invalid user', {
method: 'addRoomLeader',
});
}
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: 'addRoomLeader',
});
}
if (subscription.roles && Array.isArray(subscription.roles) === true && subscription.roles.includes('leader') === true) {
throw new Meteor.Error('error-user-already-leader', 'User is already a leader', {
method: 'addRoomLeader',
});
}
View on GitHub (pinned to b2c16d5842)
Solutions
- Verify the target userId exists and has a username (e.g. GET /v1/users.info) before calling.
- Refresh the member list so deleted users cannot be selected.
- If usernames are missing on legitimate users, fix the user records first.
Defensive patterns
Strategy: validation
Validate before calling
// confirm target user exists with a username before promoting
const res = await fetch(`/api/v1/users.info?userId=${userId}`, { headers }).then((r) => r.json());
if (!res.success || !res.user?.username) {
throw new Error('Target user missing or has no username');
} Type guard
function isPromotableUser(u: { _id?: string; username?: string } | null | undefined): u is { _id: string; username: string } {
return !!u?._id && typeof u.username === 'string' && u.username.length > 0;
} Try / catch
try {
await Meteor.callAsync('addRoomLeader', rid, userId);
} catch (e: any) {
if (e?.error === 'error-invalid-user') {
// target userId invalid: refresh the member list, pick again
}
} Prevention
- Refresh member lists so deleted users cannot be selected.
- Reject userIds that are empty or not 17-char Mongo ids.
- Skip app/bot accounts without usernames in role-management UIs.
When it happens
Trigger: Passing a deleted or never-existing userId; targeting an app/bot or shadow user created without a username; the user was deleted between the member list rendering and the role-change call.
Common situations: Stale member lists in admin UIs; users removed mid-session; imported accounts with null usernames.
Related errors
AI-assisted analysis of RocketChat/Rocket.Chat@b2c16d5842 (2026-08-18).
Data as JSON: /api/errors/69dd081c1f5fddc4.
Report an issue: GitHub.