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
- Confirm the user exists and has a username: await Users.findOneById(userId, { projection: { username: 1 } }).
- Fix the account data: set the username via the admin UI (Users > edit > username) or the REST user update endpoint, then retry.
- Re-fetch the userId at call time from a username lookup (Users.findOneByUsernameIgnoringCase) instead of caching IDs.
- 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
- Resolve targets by username at call time and pass the freshly fetched _id.
- Alert on user documents without usernames — they break role operations and system messages.
- Never feed IDs from external systems into method calls without a local existence check.
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.