RocketChat/Rocket.Chat · error · Meteor.Error
error-invalid-room
error-invalid-room
Error message
Invalid room
What it means
loadMissedMessages throws error-invalid-room when rid is falsy. Because check(rid, String) runs first and enforces the type, the only value that reaches this throw is the empty string '' (null/undefined/number fail earlier with a Match failed error instead). Two quirks: the error's method metadata says 'getUsersOfRoom' — a copy-paste artifact — and the method is deprecated since 9.0.0 in favor of /v1/chat.syncMessages. Note that failing canAccessRoomIdAsync does NOT throw here; it returns false.
Source
Thrown at apps/meteor/server/meteor-methods/messages/loadMissedMessages.ts:26
import { methodDeprecationLogger } from '../../lib/deprecationWarningLogger';
declare module '@rocket.chat/ddp-client' {
// eslint-disable-next-line @typescript-eslint/naming-convention
interface ServerMethods {
loadMissedMessages(rid: IRoom['_id'], ts: Date): Promise<false | IMessage[]>;
}
}
Meteor.methods<ServerMethods>({
async loadMissedMessages(rid, start) {
methodDeprecationLogger.method('loadMissedMessages', '9.0.0', '/v1/chat.syncMessages');
check(rid, String);
check(start, Date);
const fromId = Meteor.userId() ?? undefined;
if (!rid) {
throw new Meteor.Error('error-invalid-room', 'Invalid room', { method: 'getUsersOfRoom' });
}
if (!(await canAccessRoomIdAsync(rid, fromId))) {
return false;
}
return Messages.findVisibleByRoomIdAfterTimestamp(rid, start, true, {
sort: {
ts: -1,
},
}).toArray();
},
});
View on GitHub (pinned to b2c16d5842)
Solutions
- Guard rid before calling — only call when it is a non-empty string
- Fix the source of the empty rid (await the room record, validate route params)
- Migrate to /v1/chat.syncMessages, which validates its own input
Example fix
// before
const messages = await Meteor.callAsync('loadMissedMessages', rid, lastSync);
// after
if (typeof rid !== 'string' || rid.length === 0) {
// wait for the room id instead of calling with ''
return;
}
const messages = await Meteor.callAsync('loadMissedMessages', rid, lastSync); Defensive patterns
Strategy: validation
Validate before calling
if (typeof rid !== 'string' || rid.length === 0) {
// wait for the room record — never call loadMissedMessages with ''
} Type guard
const isNonEmptyRoomId = (rid: unknown): rid is string => typeof rid === 'string' && rid.trim().length > 0;
Prevention
- Derive rid from a loaded room record or subscription, never from an unvalidated variable
- Remember check() already rejects non-strings with Match failed — this error means the empty string specifically
- Prefer /v1/chat.syncMessages; the DDP method is deprecated since 9.0.0 and its error metadata mislabels the method
When it happens
Trigger: Meteor.call('loadMissedMessages', '', startDate) — the rid comes from an unset variable, an empty route param, or a room record that has not loaded yet when the sync fires.
Common situations: Races where loadMissedMessages fires before the room subscription delivers the rid; refactors that renamed variables and accidentally pass ''; optional :rid route params rendered without validation.
Related errors
- error-invalid-room
- error-the-field-is-required
- invalid-command-usage
- error-invalid-user
- error-room-does-not-exist
AI-assisted analysis of RocketChat/Rocket.Chat@b2c16d5842 (2026-08-18).
Data as JSON: /api/errors/87880360f8b2acc2.
Report an issue: GitHub.