{"record":{"id":"7eefd32ca4073ef9","repo":"RocketChat/Rocket.Chat","slug":"error-invalid-room-7eefd3","errorCode":"error-invalid-room","errorMessage":"Invalid room","messagePattern":"Invalid room","errorType":"exception","errorClass":"Meteor.Error","httpStatus":null,"severity":"error","filePath":"apps/meteor/server/meteor-methods/rooms/saveRoomSettings.ts","lineNumber":463,"sourceCode":"export async function saveRoomSettings<RoomSettingName extends keyof RoomSettings>(\n\tuserId: IUser['_id'],\n\trid: IRoom['_id'],\n\tsetting: RoomSettingName,\n\tvalue: RoomSettings[RoomSettingName],\n): Promise<{ result: true; rid: IRoom['_id'] }>;\nexport async function saveRoomSettings(\n\tuserId: IUser['_id'],\n\trid: IRoom['_id'],\n\tsettings: Partial<RoomSettings> | keyof RoomSettings,\n\tvalue?: RoomSettings[keyof RoomSettings],\n): Promise<{ result: true; rid: IRoom['_id'] }> {\n\tif (!userId) {\n\t\tthrow new Meteor.Error('error-invalid-user', 'Invalid user', {\n\t\t\tfunction: 'RocketChat.saveRoomName',\n\t\t});\n\t}\n\tif (!Match.test(rid, String)) {\n\t\tthrow new Meteor.Error('error-invalid-room', 'Invalid room', {\n\t\t\tmethod: 'saveRoomSettings',\n\t\t});\n\t}\n\n\tif (typeof settings !== 'object') {\n\t\tsettings = {\n\t\t\t[settings]: value,\n\t\t};\n\t}\n\n\tif (!Object.keys(settings).every((key) => fields.includes(key as keyof typeof settings))) {\n\t\tthrow new Meteor.Error('error-invalid-settings', 'Invalid settings provided', {\n\t\t\tmethod: 'saveRoomSettings',\n\t\t});\n\t}\n\n\tconst room = await Rooms.findOneById(rid);\n","sourceCodeStart":445,"sourceCodeEnd":481,"githubUrl":"https://github.com/RocketChat/Rocket.Chat/blob/b2c16d5842cbe6b69b59bdf6fc5e5f1afcd1f0b0/apps/meteor/server/meteor-methods/rooms/saveRoomSettings.ts#L445-L481","documentation":"Before touching the database, saveRoomSettings asserts Match.test(rid, String); any non-string room id throws error-invalid-room immediately. This is a pure argument-type check, not a lookup — the same code is later reused for the room-not-found case, so distinguish them by when they fire.","triggerScenarios":"Calling saveRoomSettings with rid as a number, undefined, null, an array, or an object — most commonly passing the whole room document instead of room._id, or a rid that is undefined after a failed upstream lookup.","commonSituations":"Destructuring mistakes (room vs room._id); ids arriving as numbers from external systems; undefined rid from optional chaining gone wrong; placeholder values pasted from examples.","solutions":["Pass the room's _id string: saveRoomSettings(userId, room._id, settings)","Log typeof rid at the call site and fix the data plumbing that produced a non-string","Mirror the guard client-side: if (typeof rid !== 'string') fail fast before invoking","Use a type guard or Partial<RoomSettings> typing so the compiler catches the wrong shape"],"exampleFix":"// before\nMeteor.call('saveRoomSettings', room, { roomTopic: 'x' }); // passed the whole room document\n\n// after\nMeteor.call('saveRoomSettings', room._id, { roomTopic: 'x' });","handlingStrategy":"type-guard","validationCode":"if (typeof rid !== 'string' || rid.length === 0) {\n  throw new Error(`saveRoomSettings: invalid rid of type ${typeof rid}`);\n}","typeGuard":"const isRoomId = (v: unknown): v is string => typeof v === 'string' && v.trim().length > 0;\n\n// usage\nif (!isRoomId(rid)) { /* fix the caller before invoking */ }","tryCatchPattern":"try {\n  await Meteor.callAsync('saveRoomSettings', rid, settings);\n} catch (error) {\n  if (error instanceof Meteor.Error && error.error === 'error-invalid-room') {\n    // note: this code covers both non-string rid and room-not-found; log rid and typeof rid to tell them apart\n  }\n}","preventionTips":["Always pass room._id, never the room document or a computed index","Type method payloads explicitly so non-string ids fail at compile time","Validate rid shape at the boundary where it enters your code (API handler, job input)"],"tags":["validation","arguments","meteor-methods"],"backgroundTag":"invalid-argument-type","analyzedSha":"b2c16d5842cbe6b69b59bdf6fc5e5f1afcd1f0b0","analyzedAt":"2026-08-18T15:26:39.429Z","schemaVersion":2},"datasetVersion":"2026-08-21T13:17:26.733Z"}