RocketChat/Rocket.Chat · error · Meteor.Error
error-invalid-user
error-invalid-user
Error message
Invalid user
What it means
executeGetRoomRoles (the shared implementation behind the getRoomRoles DDP method) rejects the call when no user context was supplied (fromUser is falsy) and the workspace setting Accounts_AllowAnonymousRead is false. Room roles are only served to identified users unless the workspace explicitly enables anonymous read access.
Source
Thrown at apps/meteor/server/meteor-methods/rooms/getRoomRoles.ts:22
import { Meteor } from 'meteor/meteor';
import { canAccessRoomAsync } from '../../lib/authorization';
import type { RoomRoles } from '../../lib/roles/getRoomRoles';
import { getRoomRoles } from '../../lib/roles/getRoomRoles';
import { settings } from '../../settings';
declare module '@rocket.chat/ddp-client' {
// eslint-disable-next-line @typescript-eslint/naming-convention
interface ServerMethods {
getRoomRoles(rid: IRoom['_id']): RoomRoles[];
}
}
export const executeGetRoomRoles = async (rid: IRoom['_id'], fromUser?: IUser | null) => {
check(rid, String);
if (!fromUser && settings.get('Accounts_AllowAnonymousRead') === false) {
throw new Meteor.Error('error-invalid-user', 'Invalid user', { method: 'getRoomRoles' });
}
const room = await Rooms.findOneById(rid);
if (!room) {
throw new Meteor.Error('error-invalid-room', 'Invalid room', { method: 'getRoomRoles' });
}
if (fromUser && !(await canAccessRoomAsync(room, fromUser))) {
throw new Meteor.Error('error-invalid-user', 'Invalid user', { method: 'getRoomRoles' });
}
return getRoomRoles(rid);
};
View on GitHub (pinned to b2c16d5842)
Solutions
- Pass the logged-in user: call the DDP method only when Meteor.userId() exists, or supply fromUser = await Meteor.userAsync() when invoking executeGetRoomRoles directly
- Enable Administration -> General -> Accounts -> Accounts_AllowAnonymousRead if anonymous room reads are intended
- Redirect anonymous users to a login flow before loading room roles
Example fix
// before - direct call without user context const roles = await executeGetRoomRoles(rid); // after - pass the requesting user const user = await Meteor.userAsync(); const roles = await executeGetRoomRoles(rid, user);
Defensive patterns
Strategy: validation
Validate before calling
// pass the requesting user whenever one exists
const user = await Meteor.userAsync();
if (!user && settings.get?.('Accounts_AllowAnonymousRead') === false) {
throw new Error('login required');
}
const roles = await executeGetRoomRoles(rid, user ?? undefined); Try / catch
try {
const roles = await Meteor.callAsync('getRoomRoles', rid);
} catch (e) {
if (e instanceof Meteor.Error && e.error === 'error-invalid-user') {
// either anonymous on a closed workspace or (1494) access denied - recheck auth first
if (!Meteor.userId()) showLoginScreen();
}
} Prevention
- Always pass fromUser when calling executeGetRoomRoles directly
- Decide explicitly whether your workspace allows anonymous reads (Accounts_AllowAnonymousRead) and code accordingly
- Note this method reuses 'error-invalid-user' for access denial - inspect auth state before assuming session loss
When it happens
Trigger: Calling Meteor.call('getRoomRoles', rid) while logged out on a default workspace; invoking executeGetRoomRoles(rid) programmatically without passing the requesting user; disabling Accounts_AllowAnonymousRead while a public site still renders room content anonymously.
Common situations: Embedded/anonymous viewers of a workspace after the admin toggles Accounts_AllowAnonymousRead off; server code importing executeGetRoomRoles directly and forgetting the fromUser argument; guest access features tested without login.
Related errors
AI-assisted analysis of RocketChat/Rocket.Chat@b2c16d5842 (2026-08-18).
Data as JSON: /api/errors/38e1679152a2ad69.
Report an issue: GitHub.