RocketChat/Rocket.Chat · error · Error
error-invalid-room
error-invalid-room
Error message
error-invalid-room
What it means
executeUnbanUserFromRoom resolves the room by id with Rooms.findOneById(rid); if no room document matches, it throws the plain Error 'error-invalid-room'. Callers (e.g. the unbanUserFromRoom method or federation events) propagate this to the client.
Source
Thrown at apps/meteor/server/lib/rooms/executeUnbanUserFromRoom.ts:11
import { Message } from '@rocket.chat/core-services';
import { isBannedSubscription, isInviteSubscription, type IUser } from '@rocket.chat/core-typings';
import { Rooms, Subscriptions, Users } from '@rocket.chat/models';
import { afterUnbanFromRoomCallback } from '../callbacks/afterUnbanFromRoomCallback';
import { notifyOnRoomChangedById, notifyOnSubscriptionChanged } from '../notifyListener';
export const executeUnbanUserFromRoom = async function (rid: string, user: IUser, byUser: IUser): Promise<void> {
const room = await Rooms.findOneById(rid);
if (!room) {
throw new Error('error-invalid-room');
}
if (!user.username) {
throw new Error('error-invalid-user');
}
const subscription = await Subscriptions.findOneByRoomIdAndUserId(rid, user._id);
if (!subscription) {
throw new Error('error-invalid-subscription');
}
// if the subscription is an invite it means we were unbanned and then invited again, then
// the invite was accepted and we receive a leave event (meaning the user was unbanned), so
// at this point we just need send the message to say the user was unbanned.
if (isInviteSubscription(subscription)) {
await Message.saveSystemMessage('user-unbanned', rid, user.username, user, {
u: { _id: byUser._id, username: byUser.username },
});View on GitHub (pinned to b2c16d5842)
Solutions
- Verify the rid exists with Rooms.findOneById before calling the unban flow
- If the room was deleted, discard the stale ban entry or event instead of unbanning
- Validate federation/app event rids against current Rooms and drop orphans
Example fix
// before
await executeUnbanUserFromRoom(ridFromEvent, user, byUser);
// after
if (!(await Rooms.findOneById(rid, { projection: { _id: 1 } }))) {
throw new Meteor.Error('error-invalid-room', `Room ${rid} not found`);
}
await executeUnbanUserFromRoom(ridFromEvent, user, byUser); Defensive patterns
Strategy: validation
Validate before calling
const room = await Rooms.findOneById(rid, { projections: { _id: 1 } });
if (!room) {
throw new Meteor.Error('error-invalid-room', `Room ${rid} not found`);
}
await executeUnbanUserFromRoom(rid, user, byUser); Try / catch
try {
await executeUnbanUserFromRoom(rid, user, byUser);
} catch (err) {
if (err instanceof Error && err.message === 'error-invalid-room') {
// room gone — drop the stale ban record in the UI, nothing to unban
}
throw err;
} Prevention
- Refresh room existence before showing moderation actions
- Purge queued federation/app events referencing deleted rooms
- Use server-side rid values from subscriptions, not client-cached ones
When it happens
Trigger: Calling executeUnbanUserFromRoom with a rid that does not exist in the Rooms collection — deleted room, typo'd/truncated id, stale rid from an old UI session or federation event referencing a room purged after the ban was created.
Common situations: Unbanning from a message action clicked in a long-open browser session after the room was deleted; federation or app events replayed with stale room ids; scripts operating on exported room ids after a partial restore.
Related errors
- There must be a parent room to create a discussion.
- room-not-found
- invalid-room
- error-room-closed
- error-invalid-room
AI-assisted analysis of RocketChat/Rocket.Chat@b2c16d5842 (2026-08-18).
Data as JSON: /api/errors/ff65220be34cfb9a.
Report an issue: GitHub.