{"record":{"id":"e31e785fccd0ab6c","repo":"RocketChat/Rocket.Chat","slug":"invalid-room-e31e78","errorCode":"invalid-room","errorMessage":"Invalid room","messagePattern":"Invalid room","errorType":"exception","errorClass":"Meteor.Error","httpStatus":null,"severity":"error","filePath":"apps/meteor/server/lib/rooms/settings/saveReactWhenReadOnly.ts","lineNumber":16,"sourceCode":"import { Message } from '@rocket.chat/core-services';\nimport { Rooms } from '@rocket.chat/models';\nimport { Match } from 'meteor/check';\nimport { Meteor } from 'meteor/meteor';\n\nexport const saveReactWhenReadOnly = async function (\n\trid: string,\n\tallowReact: boolean,\n\tuser: {\n\t\t_id: string;\n\t\tusername: string;\n\t},\n\tsendMessage = true,\n) {\n\tif (!Match.test(rid, String)) {\n\t\tthrow new Meteor.Error('invalid-room', 'Invalid room', {\n\t\t\tfunction: 'RocketChat.saveReactWhenReadOnly',\n\t\t});\n\t}\n\n\tconst result = await Rooms.setAllowReactingWhenReadOnlyById(rid, allowReact);\n\n\tif (result && sendMessage) {\n\t\tconst type = allowReact ? 'room-allowed-reacting' : 'room-disallowed-reacting';\n\n\t\tawait Message.saveSystemMessage(type, rid, '', user);\n\t}\n};\n","sourceCodeStart":1,"sourceCodeEnd":29,"githubUrl":"https://github.com/RocketChat/Rocket.Chat/blob/b2c16d5842cbe6b69b59bdf6fc5e5f1afcd1f0b0/apps/meteor/server/lib/rooms/settings/saveReactWhenReadOnly.ts#L1-L29","documentation":"Thrown by saveReactWhenReadOnly when Match.test(rid, String) fails (saveReactWhenReadOnly.ts:16) — the room id argument is not a string (undefined, null, number, array, object). Meteor's Match is used here purely as an argument-type check before the DB write; nothing has been modified yet. Code 'invalid-room', details { function: 'RocketChat.saveReactWhenReadOnly' }.","triggerScenarios":"Calling saveReactWhenReadOnly(undefined, true, user) after a failed room lookup upstream; passing a room document instead of its _id; numeric ids leaking from an external system; destructuring { rid } from an object where the key is absent.","commonSituations":"REST/method handlers forwarding req.body.rid that was never sent; refactor renaming roomId → rid missing one call site; mock data using array ids.","solutions":["Pass the room _id as a string, e.g. saveReactWhenReadOnly(room._id, allowReact, user)","Guard upstream: if (typeof rid !== 'string' || !rid) bail out before calling","Check where rid was produced — usually a missing property or wrong destructuring one frame up","Match on code 'invalid-room' only after excluding genuine not-found cases (this function cannot distinguish them)"],"exampleFix":"// before\nawait saveReactWhenReadOnly(room, allowReact, user);\n\n// after\nawait saveReactWhenReadOnly(String(room._id), allowReact, user);","handlingStrategy":"type-guard","validationCode":"if (typeof rid !== 'string' || rid.length === 0) {\n\tthrow new Meteor.Error('invalid-room', 'Invalid room', { function: 'RocketChat.saveReactWhenReadOnly' });\n}\nawait saveReactWhenReadOnly(rid, allowReact, user);","typeGuard":"const isRoomId = (v: unknown): v is string => typeof v === 'string' && v.length > 0;","tryCatchPattern":null,"preventionTips":["Validate rid once at the method/endpoint boundary","Pass room._id, never the room document","Use TypeScript signatures so non-string ids fail to compile"],"tags":["room-settings","argument-validation","meteor-check","read-only"],"backgroundTag":"invalid-argument-value","analyzedSha":"b2c16d5842cbe6b69b59bdf6fc5e5f1afcd1f0b0","analyzedAt":"2026-08-18T15:26:39.429Z","contentChangedAt":"2026-08-18T15:26:39.429Z","schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}