RocketChat/Rocket.Chat · error · Meteor.Error
invalid-user
invalid-user
Error message
Invalid user
What it means
Thrown by saveRoomEncrypted when isRegisterUser(user) is false (saveRoomEncrypted.ts:19). isRegisterUser (packages/core-typings/src/IUser.ts:255) requires user.username !== undefined && user.name !== undefined, so partial user objects and nameless app/bot users fail. Code 'invalid-user', details { function: 'RocketChat.saveRoomEncrypted' }.
Source
Thrown at apps/meteor/server/lib/rooms/settings/saveRoomEncrypted.ts:19
import { Message } from '@rocket.chat/core-services';
import type { IUser } from '@rocket.chat/core-typings';
import { isRegisterUser } from '@rocket.chat/core-typings';
import { Rooms, Subscriptions } from '@rocket.chat/models';
import { Match } from 'meteor/check';
import { Meteor } from 'meteor/meteor';
import type { UpdateResult } from 'mongodb';
import { notifyOnSubscriptionChangedByRoomId } from '../../notifyListener';
export const saveRoomEncrypted = async function (rid: string, encrypted: boolean, user: IUser, sendMessage = true): Promise<UpdateResult> {
if (!Match.test(rid, String)) {
throw new Meteor.Error('invalid-room', 'Invalid room', {
function: 'RocketChat.saveRoomEncrypted',
});
}
if (!isRegisterUser(user)) {
throw new Meteor.Error('invalid-user', 'Invalid user', {
function: 'RocketChat.saveRoomEncrypted',
});
}
const update = await Rooms.saveEncryptedById(rid, encrypted);
if (update && sendMessage) {
const type = encrypted ? 'room_e2e_enabled' : 'room_e2e_disabled';
await Message.saveSystemMessage(type, rid, user.username, user);
}
if (encrypted) {
const { modifiedCount } = await Subscriptions.disableAutoTranslateByRoomId(rid);
if (modifiedCount) {
void notifyOnSubscriptionChangedByRoomId(rid);
}
}
return update;View on GitHub (pinned to b2c16d5842)
Solutions
- Load the full user: const user = await Users.findOneById(userId) and pass that
- Ensure the user profile has a non-empty name and a username
- Pre-check with isRegisterUser(user) from '@rocket.chat/core-typings'
- Match on code 'invalid-user' (no error- prefix) when catching
Example fix
// before
await saveRoomEncrypted(rid, encrypted, { _id: uid } as IUser);
// after
const user = await Users.findOneById(uid);
if (!user || !isRegisterUser(user)) {
throw new Meteor.Error('invalid-user', 'Invalid user', { function: 'RocketChat.saveRoomEncrypted' });
}
await saveRoomEncrypted(rid, encrypted, user); Defensive patterns
Strategy: type-guard
Validate before calling
const user = await Users.findOneById(userId);
if (!user || !isRegisterUser(user)) {
throw new Meteor.Error('invalid-user', 'Invalid user', { function: 'RocketChat.saveRoomEncrypted' });
}
await saveRoomEncrypted(rid, encrypted, user); Type guard
import { isRegisterUser } from '@rocket.chat/core-typings';
// narrows IUser to IRegisterUser when username AND name are defined
const canOperate = (u: IUser): boolean => isRegisterUser(u); Prevention
- Fetch the full user document rather than trusting partial session projections
- Ensure profiles have name set (bots/apps often lack it)
- Catch on exact code 'invalid-user'
When it happens
Trigger: Passing a user stub like { _id } from a method context without fetching the document; bots/apps users lacking name; test fixtures with only _id/username; passing the acting app user instead of the human owner.
Common situations: Server code using Meteor.user() partial projections that omitted name; scripts driving the e2e toggle with hardcoded minimal users.
Related errors
AI-assisted analysis of RocketChat/Rocket.Chat@b2c16d5842 (2026-08-18).
Data as JSON: /api/errors/8ddf29f09c88a17b.
Report an issue: GitHub.