RocketChat/Rocket.Chat · error · Meteor.Error
invalid-room
invalid-room
Error message
Invalid room
What it means
Thrown by saveRoomReadOnly when Match.test(rid, String) fails (saveRoomReadOnly.ts:14) — the room id is not a string (undefined/null/number/object). Pure argument-type gate ahead of Rooms.setReadOnlyById and the system messages; nothing is modified when it throws. Code 'invalid-room', details { function: 'RocketChat.saveRoomReadOnly' }.
Source
Thrown at apps/meteor/server/lib/rooms/settings/saveRoomReadOnly.ts:14
import { Message } from '@rocket.chat/core-services';
import type { IUser } from '@rocket.chat/core-typings';
import { Rooms } from '@rocket.chat/models';
import { Match } from 'meteor/check';
import { Meteor } from 'meteor/meteor';
export async function saveRoomReadOnly(
rid: string,
readOnly: boolean,
user: Required<Pick<IUser, '_id' | 'username' | 'name'>>,
sendMessage = true,
) {
if (!Match.test(rid, String)) {
throw new Meteor.Error('invalid-room', 'Invalid room', {
function: 'RocketChat.saveRoomReadOnly',
});
}
const result = await Rooms.setReadOnlyById(rid, readOnly);
if (result && sendMessage) {
if (readOnly) {
await Message.saveSystemMessage('room-set-read-only', rid, '', user);
} else {
await Message.saveSystemMessage('room-removed-read-only', rid, '', user);
}
}
return result;
}
View on GitHub (pinned to b2c16d5842)
Solutions
- Pass the room _id string as the first argument
- Validate rid at the method/endpoint boundary before calling
- Inspect the caller for missing destructuring or wrong property name
- Add a lightweight unit test that non-string rid throws 'invalid-room' early
Example fix
// before
await saveRoomReadOnly(body.rid, readOnly, user);
// after
if (typeof body.rid !== 'string' || body.rid.length === 0) {
throw new Meteor.Error('invalid-room', 'Invalid room', { function: 'RocketChat.saveRoomReadOnly' });
}
await saveRoomReadOnly(body.rid, readOnly, 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.saveRoomReadOnly' });
}
await saveRoomReadOnly(rid, readOnly, user); Type guard
const isRoomId = (v: unknown): v is string => typeof v === 'string' && v.length > 0;
Prevention
- Pass room._id as a string; never the document or ObjectId
- Validate the method payload once at the boundary
- Keep rid naming uniform across settings handlers
When it happens
Trigger: saveRoomReadOnly(undefined, true, user) from an unvalidated method payload; passing room document/ObjectId; variable renamed between roomId and rid leaving one call site broken.
Common situations: Channel settings forms with missing hidden rid inputs; REST wrappers forwarding raw body fields; tests using placeholder ids.
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/9e9958471abedfac.
Report an issue: GitHub.