RocketChat/Rocket.Chat · error · Meteor.Error
error-invalid-room
error-invalid-room
Error message
Invalid room
What it means
unmuteUserInRoom loads the room with Rooms.findOneById(data.rid); a null result throws error-invalid-room before any moderation logic or permission checks on the target run.
Source
Thrown at apps/meteor/server/meteor-methods/rooms/unmuteUserInRoom.ts:29
declare module '@rocket.chat/ddp-client' {
// eslint-disable-next-line @typescript-eslint/naming-convention
interface ServerMethods {
unmuteUserInRoom(data: { rid: IRoom['_id']; username: string }): boolean;
}
}
export const unmuteUserInRoom = async (fromId: string, data: { rid: IRoom['_id']; username: string }): Promise<boolean> => {
if (!fromId || !(await hasPermissionAsync(fromId, 'mute-user', data.rid))) {
throw new Meteor.Error('error-not-allowed', 'Not allowed', {
method: 'unmuteUserInRoom',
});
}
const room = await Rooms.findOneById(data.rid);
if (!room) {
throw new Meteor.Error('error-invalid-room', 'Invalid room', {
method: 'unmuteUserInRoom',
});
}
if (!(await roomCoordinator.getRoomDirectives(room.t).allowMemberAction(room, RoomMemberActions.MUTE, fromId))) {
throw new Meteor.Error('error-invalid-room-type', `${room.t} is not a valid room type`, {
method: 'unmuteUserInRoom',
type: room.t,
});
}
const subscription = await Subscriptions.findOneByRoomIdAndUsername(data.rid, data.username, {
projection: { _id: 1 },
});
if (!subscription) {
throw new Meteor.Error('error-user-not-in-room', 'User is not in this room', {
method: 'unmuteUserInRoom',View on GitHub (pinned to b2c16d5842)
Solutions
- Verify the room exists before invoking (REST rooms.info or the rooms collection on the server)
- Refresh room ids in long-lived integrations instead of caching them indefinitely
- Treat error-invalid-room from moderation methods as 'room gone' and clean up the UI/integration state
Example fix
// before
Meteor.call('unmuteUserInRoom', { rid, username }); // rid was deleted
// after
const room = await Rooms.findOneById(rid, { projection: { _id: 1 } });
if (!room) {
// refresh state; do not call the method
} else {
Meteor.call('unmuteUserInRoom', { rid: room._id, username });
} Defensive patterns
Strategy: validation
Validate before calling
const room = await Rooms.findOneById(rid, { projection: { _id: 1 } });
if (!room) {
// room no longer exists: refresh state instead of calling unmuteUserInRoom
} Try / catch
try {
await Meteor.callAsync('unmuteUserInRoom', { rid, username });
} catch (error) {
if (error instanceof Meteor.Error && error.error === 'error-invalid-room') {
// room gone: discard the moderation action and update UI state
}
} Prevention
- Look up the room immediately before moderation actions; rooms can vanish between render and click
- Evict deleted rooms from cached lists and menus
- In integrations, re-resolve rids per operation rather than caching forever
When it happens
Trigger: Calling unmuteUserInRoom with the id of a deleted or nonexistent room, an id from another workspace, or a typo'd/malformed rid.
Common situations: Moderation UI acting on a room deleted moments earlier; stale room ids cached in integrations or bots; ids that lost characters when copied.
Related errors
AI-assisted analysis of RocketChat/Rocket.Chat@b2c16d5842 (2026-08-18).
Data as JSON: /api/errors/4db250ae0d3c6c9c.
Report an issue: GitHub.