RocketChat/Rocket.Chat · error · Meteor.Error
error-invalid-user
error-invalid-user
Error message
Invalid user
What it means
loadHistory is the only history method with a guest mode: it supports anonymous reads when the workspace setting Accounts_AllowAnonymousRead is enabled. It throws error-invalid-user when the caller has no user record AND Accounts_AllowAnonymousRead === false. If the setting is enabled, anonymous loads proceed to the normal room-access check, which returns false rather than throwing when access is denied.
Source
Thrown at apps/meteor/server/meteor-methods/messages/loadHistory.ts:39
showThreadMessages?: boolean,
):
| {
messages: IMessage[];
firstUnread: IMessage | undefined;
unreadNotLoaded: number;
}
| false;
}
}
Meteor.methods<ServerMethods>({
async loadHistory(rid, end, limit = 20, ls, showThreadMessages = true) {
methodDeprecationLogger.method('loadHistory', '9.0.0', '/v1/rooms.history');
check(rid, String);
const fromUser = await Meteor.userAsync();
if (!fromUser && settings.get('Accounts_AllowAnonymousRead') === false) {
throw new Meteor.Error('error-invalid-user', 'Invalid user', {
method: 'loadHistory',
});
}
const room = await Rooms.findOneById(rid, { projection: { ...roomAccessAttributes, t: 1, sysMes: 1 } });
if (!room) {
return false;
}
// this checks the Allow Anonymous Read setting, so no need to check again
if (!(await canAccessRoomAsync(room, fromUser || undefined))) {
return false;
}
// if fromId is undefined and it passed the previous check, the user is reading anonymously
if (!fromUser) {
return loadMessageHistory({ rid, end, limit, ls, showThreadMessages, room });
}View on GitHub (pinned to b263243745)
Solutions
- Authenticate the visitor before loading history
- Enable Accounts_AllowAnonymousRead (Administration → Accounts) if guest reading of public channels is intended
- Catch the error and redirect anonymous visitors to the login page
Example fix
// before
const result = await Meteor.callAsync('loadHistory', rid, end, limit, ls);
// after (client)
const anonReadAllowed = useSetting('Accounts_AllowAnonymousRead');
if (!Meteor.userId() && !anonReadAllowed) {
showLoginPrompt();
} else {
const result = await Meteor.callAsync('loadHistory', rid, end, limit, ls);
} Defensive patterns
Strategy: validation
Validate before calling
const anonReadAllowed = publicSettings.get('Accounts_AllowAnonymousRead') ?? false;
if (!Meteor.userId() && !anonReadAllowed) {
// anonymous history is disabled — send the visitor to login
} Try / catch
try {
const history = await Meteor.callAsync('loadHistory', rid, end, limit, ls);
} catch (error) {
if (error instanceof Meteor.Error && error.error === 'error-invalid-user') {
showLoginPrompt(); // guest read disabled and no session
return false;
}
throw error;
} Prevention
- For guest-accessible apps, feature-detect Accounts_AllowAnonymousRead before rendering channel history
- Do not assume loadHistory works anonymously — it depends on the workspace setting
- Redirect anonymous visitors to login when the setting is off instead of retrying
When it happens
Trigger: A logged-out visitor opening a public channel while Accounts_AllowAnonymousRead is disabled (the default); anonymous crawlers or link previews hitting a workspace where guest read was turned off; DDP clients without a login calling loadHistory.
Common situations: An admin disables Accounts_AllowAnonymousRead after previously allowing guests; bots scraping public channels without credentials; guest sessions continuing after the setting changed.
Understand the failure class
Background: error-invalid-user: "Invalid user" errors in Rocket.Chat — what they mean and how to fix them — this error's family across 2 libraries.
Related errors
AI-assisted analysis of RocketChat/Rocket.Chat@b263243745 (2026-08-18).
Data as JSON: /api/errors/13114107b5ec3754.
Report an issue: GitHub.