RocketChat/Rocket.Chat · error · Meteor.Error
error-invalid-user
error-invalid-user
Error message
Invalid user
What it means
The getUsersOfRoom method requires a logged-in caller: Meteor.userId() returned null, so it throws error-invalid-user before any room lookup. Membership listing is never served to anonymous connections, even for public rooms.
Source
Thrown at apps/meteor/server/meteor-methods/users/getUsersOfRoom.ts:37
filter?: string,
): {
total: number;
records: IUser[];
};
}
}
Meteor.methods<ServerMethods>({
async getUsersOfRoom(rid, showAll, { limit, skip } = {}, filter) {
if (!rid) {
throw new Meteor.Error('error-invalid-room', 'Invalid room', { method: 'getUsersOfRoom' });
}
check(rid, String);
const userId = Meteor.userId();
if (!userId) {
throw new Meteor.Error('error-invalid-user', 'Invalid user', { method: 'getUsersOfRoom' });
}
const room = await Rooms.findOneById(rid, { projection: { ...roomAccessAttributes, broadcast: 1 } });
if (!room) {
throw new Meteor.Error('error-not-allowed', 'Not allowed', { method: 'getUsersOfRoom' });
}
if (!(await canAccessRoomAsync(room, { _id: userId }))) {
throw new Meteor.Error('not-authorized', 'Not Authorized', { method: 'getUsersOfRoom' });
}
if (room.broadcast && !(await hasPermissionAsync(userId, 'view-broadcast-member-list', rid))) {
throw new Meteor.Error('error-not-allowed', 'Not allowed', { method: 'getUsersOfRoom' });
}
// TODO this is currently counting deactivated users
const total = await Subscriptions.countByRoomIdWhenUsernameExists(rid);
View on GitHub (pinned to b2c16d5842)
Solutions
- Guard the call with Meteor.userId() and skip member listing for anonymous views
- Re-authenticate and retry once on this error
- Ensure the call uses the same DDP connection the user logged in on
Example fix
// before
Meteor.callAsync('getUsersOfRoom', rid, showAll, {}, filter);
// after
if (!Meteor.userId()) {
throw new Error('login required');
}
await Meteor.callAsync('getUsersOfRoom', rid, showAll, {}, filter); Defensive patterns
Strategy: validation
Validate before calling
if (!Meteor.userId()) {
return; // no session — skip member fetch
}
await Meteor.callAsync('getUsersOfRoom', rid, showAll, { limit, skip }, filter); Try / catch
try {
await Meteor.callAsync('getUsersOfRoom', rid, showAll, {}, filter);
} catch (err) {
if ((err as { error?: string }).error === 'error-invalid-user') {
// re-login and retry once
}
} Prevention
- Require a session before mounting member-list UI
- Handle expired tokens centrally instead of per component
- Keep the DDP connection used for login and for method calls the same
When it happens
Trigger: Meteor.callAsync('getUsersOfRoom', rid, ...) on a connection without a valid login token — guest session, after logout, or expired resume token.
Common situations: Member lists rendered on public/preview pages; token expiry on long-lived tabs; calls racing a logout or server restart that cleared tokens.
Related errors
AI-assisted analysis of RocketChat/Rocket.Chat@b2c16d5842 (2026-08-18).
Data as JSON: /api/errors/f88b51110add682a.
Report an issue: GitHub.