{"record":{"id":"4f3f4962dfe330fa","repo":"RocketChat/Rocket.Chat","slug":"error-room-param-not-provided","errorCode":"error-room-param-not-provided","errorMessage":"The parameter \"roomId\" or \"roomName\" is required","messagePattern":"The parameter \"roomId\" or \"roomName\" is required","errorType":"exception","errorClass":"Meteor.Error","httpStatus":null,"severity":"error","filePath":"apps/meteor/server/api/v1/groups.ts","lineNumber":74,"sourceCode":"import { leaveRoomMethod } from '../../meteor-methods/rooms/leaveRoom';\nimport { removeRoomLeader } from '../../meteor-methods/rooms/removeRoomLeader';\nimport { removeRoomModerator } from '../../meteor-methods/rooms/removeRoomModerator';\nimport { removeRoomOwner } from '../../meteor-methods/rooms/removeRoomOwner';\nimport { removeUserFromRoomMethod } from '../../meteor-methods/rooms/removeUserFromRoom';\nimport { saveRoomSettings } from '../../meteor-methods/rooms/saveRoomSettings';\nimport { executeUnarchiveRoom } from '../../meteor-methods/rooms/unarchiveRoom';\nimport { API } from '../api';\nimport { addUserToFileObj } from '../lib/addUserToFileObj';\nimport { composeRoomWithLastMessage } from '../lib/composeRoomWithLastMessage';\nimport { getPaginationItems } from '../lib/getPaginationItems';\nimport { getUserFromParams, getUserListFromParams, getUsernameListFromParams } from '../lib/getUserFromParams';\n\nasync function getRoomFromParams(params: { roomId?: string } | { roomName?: string }): Promise<IRoom> {\n\tif (\n\t\t(!('roomId' in params) && !('roomName' in params)) ||\n\t\t('roomId' in params && !(params as { roomId?: string }).roomId && 'roomName' in params && !(params as { roomName?: string }).roomName)\n\t) {\n\t\tthrow new Meteor.Error('error-room-param-not-provided', 'The parameter \"roomId\" or \"roomName\" is required');\n\t}\n\n\tconst roomOptions = {\n\t\tprojection: {\n\t\t\t...roomAccessAttributes,\n\t\t\tt: 1,\n\t\t\tro: 1,\n\t\t\tname: 1,\n\t\t\tfname: 1,\n\t\t\tprid: 1,\n\t\t\tarchived: 1,\n\t\t\tbroadcast: 1,\n\t\t},\n\t};\n\n\tconst room = await (() => {\n\t\tif ('roomId' in params) {\n\t\t\treturn Rooms.findOneById(params.roomId || '', roomOptions);","sourceCodeStart":56,"sourceCodeEnd":92,"githubUrl":"https://github.com/RocketChat/Rocket.Chat/blob/e4b8178b205510181a96ceefee043d0abcd13e5a/apps/meteor/server/api/v1/groups.ts#L56-L92","documentation":"Thrown by getRoomFromParams, the shared resolver behind findPrivateGroupByIdOrName and most groups.* mutation endpoints (groups.addAll, groups.addModerator, groups.kick, ...), when the request identifies no target room: neither a roomId nor a roomName key is present, or both keys are present and both are empty strings. One non-empty value of either kind is required. Quirk: sending only roomId as an empty string does NOT raise this error - it falls through to a lookup of '' and surfaces error-room-not-found instead.","triggerScenarios":"POST groups.addAll with body { activeUsersOnly: true } (room target forgotten); body containing { roomId: '', roomName: '' }; clients that build params from optional variables that are undefined on both branches, so the keys are stripped by JSON.stringify.","commonSituations":"Copy-pasting a groups.* call template and forgetting the room selector; branching code that sets roomId in one branch and roomName in another but neither in a third; passing the room inside a nested object or wrong key spelling (rid, groupId, name) instead of roomId/roomName.","solutions":["Include exactly one non-empty roomId or roomName (top-level) in the request body for POST endpoints / query for GET endpoints","If you only have the room name, send roomName; if you have the id from rooms/info or a subscription, send roomId","Guard on the client: build params only when one of the two is truthy, and fail fast with your own message otherwise"],"exampleFix":"// before\nawait sdk.post('groups.addAll', { activeUsersOnly: true });\n\n// after\nawait sdk.post('groups.addAll', { roomId, activeUsersOnly: true });","handlingStrategy":"validation","validationCode":"function roomTarget(params) {\n  const target = params.roomId?.trim() ? { roomId: params.roomId.trim() }\n    : params.roomName?.trim() ? { roomName: params.roomName.trim() }\n    : null;\n  if (!target) throw new Error('provide a non-empty roomId or roomName');\n  return target;\n}\n// sdk.post('groups.addAll', { ...roomTarget(cfg), activeUsersOnly: true })","typeGuard":"type RoomTarget = { roomId: string } | { roomName: string };\nconst isRoomTarget = (p: Partial<{ roomId?: unknown; roomName?: unknown }>): p is RoomTarget =>\n  (typeof p.roomId === 'string' && p.roomId.length > 0) || (typeof p.roomName === 'string' && p.roomName.length > 0);","tryCatchPattern":"try { await sdk.post(route, body); } catch (e) {\n  if (e.error === 'error-room-param-not-provided') failFast('missing room selector');\n}","preventionTips":["Wrap every groups.* call in one helper that requires roomId or roomName up front","Prefer roomId - ids survive renames and avoid casing issues","Beware JSON.stringify dropping undefined fields: your 'roomId: maybeId' silently disappears"],"tags":["rest-api","groups","room-resolution","required-parameter"],"backgroundTag":"missing-required-argument","analyzedSha":"e4b8178b205510181a96ceefee043d0abcd13e5a","analyzedAt":"2026-08-18T15:26:39.429Z","contentChangedAt":"2026-08-18T15:26:39.429Z","schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}