RocketChat/Rocket.Chat · error · Meteor.Error
invalid-room
invalid-room
Error message
Invalid room
What it means
Thrown by saveRoomEncrypted when Match.test(rid, String) fails (saveRoomEncrypted.ts:13). First guard of the function; a second guard ('invalid-user') validates the user right after. Nothing is persisted when it throws. Code 'invalid-room', details { function: 'RocketChat.saveRoomEncrypted' }.
Source
Thrown at apps/meteor/server/lib/rooms/settings/saveRoomEncrypted.ts:13
import { Message } from '@rocket.chat/core-services';
import type { IUser } from '@rocket.chat/core-typings';
import { isRegisterUser } from '@rocket.chat/core-typings';
import { Rooms, Subscriptions } from '@rocket.chat/models';
import { Match } from 'meteor/check';
import { Meteor } from 'meteor/meteor';
import type { UpdateResult } from 'mongodb';
import { notifyOnSubscriptionChangedByRoomId } from '../../notifyListener';
export const saveRoomEncrypted = async function (rid: string, encrypted: boolean, user: IUser, sendMessage = true): Promise<UpdateResult> {
if (!Match.test(rid, String)) {
throw new Meteor.Error('invalid-room', 'Invalid room', {
function: 'RocketChat.saveRoomEncrypted',
});
}
if (!isRegisterUser(user)) {
throw new Meteor.Error('invalid-user', 'Invalid user', {
function: 'RocketChat.saveRoomEncrypted',
});
}
const update = await Rooms.saveEncryptedById(rid, encrypted);
if (update && sendMessage) {
const type = encrypted ? 'room_e2e_enabled' : 'room_e2e_disabled';
await Message.saveSystemMessage(type, rid, user.username, user);
}
if (encrypted) {View on GitHub (pinned to b2c16d5842)
Solutions
- Pass the room _id string as the first argument
- Validate rid before calling and return an explicit bad-request from the handler
- Check the client payload for the e2e toggle if this surfaces via a meteor method
- Fix the user guard too if the same call passes partial users (next check is isRegisterUser)
Example fix
// before
await saveRoomEncrypted(body.rid, body.encrypted, user);
// after
if (typeof body.rid !== 'string') {
throw new Meteor.Error('invalid-room', 'Invalid room', { function: 'RocketChat.saveRoomEncrypted' });
}
await saveRoomEncrypted(body.rid, body.encrypted, user); Defensive patterns
Strategy: type-guard
Validate before calling
if (typeof rid !== 'string' || rid.length === 0) {
throw new Meteor.Error('invalid-room', 'Invalid room', { function: 'RocketChat.saveRoomEncrypted' });
}
await saveRoomEncrypted(rid, encrypted, user); Type guard
const isRoomId = (v: unknown): v is string => typeof v === 'string' && v.length > 0;
Prevention
- Have the e2e toggle client send the current room._id from live room data
- Validate rid AND isRegisterUser(user) together for this function
- Return 400 early from method handlers on malformed payloads
When it happens
Trigger: Calling saveRoomEncrypted with a rid that is undefined/number/room document; e2e toggle handler receiving a bad room id from the client; passing ObjectId instead of string.
Common situations: E2E toggle UI sending stale room ids after the room closed; federation/app code building rid from parts and occasionally producing undefined.
Understand the failure class
Background: "Must be a positive integer", "Invalid value", "Unsupported": the invalid-argument-value error family, when a library rejects the value you pass — this error's family across 35 libraries.
Related errors
AI-assisted analysis of RocketChat/Rocket.Chat@b2c16d5842 (2026-08-18).
Data as JSON: /api/errors/ce66d110c9f197cc.
Report an issue: GitHub.