RocketChat/Rocket.Chat · error · Meteor.Error
invalid-room
invalid-room
Error message
Invalid room
What it means
Thrown by saveRoomAnnouncement when Match.test(rid, String) fails (saveRoomAnnouncement.ts:15). It is a pure argument-type gate in front of the announcement update — rid must be a string room _id; nothing is written when it throws. Code 'invalid-room', details { function: 'RocketChat.saveRoomAnnouncement' }.
Source
Thrown at apps/meteor/server/lib/rooms/settings/saveRoomAnnouncement.ts:15
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';
import type { UpdateResult } from 'mongodb';
export const saveRoomAnnouncement = async function (
rid: string,
roomAnnouncement: string,
user: IUser,
sendMessage = true,
): Promise<UpdateResult> {
if (!Match.test(rid, String)) {
throw new Meteor.Error('invalid-room', 'Invalid room', {
function: 'RocketChat.saveRoomAnnouncement',
});
}
let message;
let announcementDetails;
if (typeof roomAnnouncement === 'string') {
message = roomAnnouncement;
} else {
({ message, ...announcementDetails } = roomAnnouncement);
}
const updated = await Rooms.setAnnouncementById(rid, message, announcementDetails);
if (updated && sendMessage) {
await Message.saveSystemMessage('room_changed_announcement', rid, message, user);
}
return updated;View on GitHub (pinned to b2c16d5842)
Solutions
- Pass the room's _id string (room._id), not its name or an ObjectId instance
- Validate at the boundary: typeof rid === 'string' && rid.length > 0 before calling
- Log the received rid at the API entry point to catch missing form/body fields
- Write tests that call the function with a real rid to catch signature drift
Example fix
// before
await saveRoomAnnouncement(roomId, announcement, user); // roomId may be undefined
// after
if (typeof roomId !== 'string' || roomId.length === 0) {
throw new Meteor.Error('invalid-room', 'Invalid room', { function: 'RocketChat.saveRoomAnnouncement' });
}
await saveRoomAnnouncement(roomId, announcement, 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.saveRoomAnnouncement' });
}
await saveRoomAnnouncement(rid, announcement, user); Type guard
const isRoomId = (v: unknown): v is string => typeof v === 'string' && v.length > 0;
Prevention
- Bind the rid form field explicitly in settings UIs
- Reject requests without a string rid at the handler with a 400
- Keep variable naming consistent (rid everywhere) to avoid undefined leaking from renames
When it happens
Trigger: Calling saveRoomAnnouncement(undefined, text, user) because rid came from a form param that was never bound; passing the room name instead of the _id; passing a Mongo.ObjectId object instead of its string form.
Common situations: REST handlers forwarding unvalidated body fields; UI code using room.name where room._id was intended; migration code that assumed ids stay numbers.
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/9c5413b282d333d7.
Report an issue: GitHub.