RocketChat/Rocket.Chat · error · Meteor.Error
error-invalid-room
error-invalid-room
Error message
Invalid room
What it means
Thrown by executeArchiveRoom when Rooms.findOneById(rid) returns null: no room document matches the id passed to archiveRoom. The room record is required for the subsequent type-directive and permission checks, so a nonexistent room aborts immediately with error-invalid-room.
Source
Thrown at apps/meteor/server/meteor-methods/rooms/archiveRoom.ts:30
declare module '@rocket.chat/ddp-client' {
// eslint-disable-next-line @typescript-eslint/naming-convention
interface ServerMethods {
archiveRoom(rid: string): Promise<void>;
}
}
export const executeArchiveRoom = async (userId: string, rid: string) => {
check(rid, String);
const user = await Users.findOneById(userId, { projection: { username: 1, name: 1 } });
if (!user || !isRegisterUser(user)) {
throw new Meteor.Error('error-invalid-user', 'Invalid user', { method: 'archiveRoom' });
}
const room = await Rooms.findOneById(rid);
if (!room) {
throw new Meteor.Error('error-invalid-room', 'Invalid room', { method: 'archiveRoom' });
}
if (!(await roomCoordinator.getRoomDirectives(room.t).allowMemberAction(room, RoomMemberActions.ARCHIVE, userId))) {
throw new Meteor.Error('error-direct-message-room', `rooms type: ${room.t} can not be archived`, { method: 'archiveRoom' });
}
if (!(await hasPermissionAsync(userId, 'archive-room', room._id))) {
throw new Meteor.Error('error-not-authorized', 'Not authorized', { method: 'archiveRoom' });
}
return archiveRoom(rid, user);
};
Meteor.methods<ServerMethods>({
async archiveRoom(rid) {
methodDeprecationLogger.method('archiveRoom', '9.0.0', '/v1/channels.archive');
const userId = Meteor.userId();
if (!userId) {View on GitHub (pinned to b2c16d5842)
Solutions
- Confirm the room exists immediately before the call (e.g. GET /api/v1/rooms.info or the live local rooms cache).
- Refresh the client's room subscriptions so deleted rooms disappear from the UI.
- In automations, treat error-invalid-room as already-removed and skip it.
Example fix
// before
Meteor.call('archiveRoom', rid);
// after
const room = roomsCollection.findOne({ _id: rid }); // local, subscription-fed cache
if (!room) {
removeRoomFromList(rid); // room vanished - sync UI instead of erroring
} else {
Meteor.call('archiveRoom', rid);
} Defensive patterns
Strategy: validation
Validate before calling
// client minimongo pre-check against the active rooms subscription
const room = roomsCollection.findOne({ _id: rid });
if (!room) {
// rid no longer resolves - refresh subscriptions or drop the room from the UI
} Try / catch
try {
await Meteor.callAsync('archiveRoom', rid);
} catch (e) {
if (e instanceof Meteor.Error && e.error === 'error-invalid-room') {
// room already gone: sync local state and move on
removeRoomFromList(rid);
return;
}
throw e;
} Prevention
- Read rids from live subscriptions, never from persisted state that can outlive the room.
- Before bulk archiving, re-fetch the room list immediately before iterating.
- Treat error-invalid-room in automations as a benign already-deleted outcome.
When it happens
Trigger: Meteor.call('archiveRoom', rid) where rid was deleted after the client loaded it (stale UI/subscription); passing a subscription _id or team id where the room _id is expected; scripts using exported room lists that are out of date.
Common situations: Archiving from a stale tab after another admin removed the room; rid typos or truncation in automation scripts; race where deletion completes between the client's check and the server's lookup.
Related errors
AI-assisted analysis of RocketChat/Rocket.Chat@b2c16d5842 (2026-08-18).
Data as JSON: /api/errors/98d1c75d18115c4f.
Report an issue: GitHub.