{"record":{"id":"ac30af424b0dd9f8","repo":"RocketChat/Rocket.Chat","slug":"error-invalid-room-ac30af","errorCode":"error-invalid-room","errorMessage":"Invalid room","messagePattern":"Invalid room","errorType":"exception","errorClass":"Meteor.Error","httpStatus":400,"severity":"error","filePath":"apps/meteor/server/api/v1/im.ts","lineNumber":991,"sourceCode":"\t\t200: ajv.compile<void>({\n\t\t\ttype: 'object',\n\t\t\tproperties: {\n\t\t\t\tsuccess: { type: 'boolean', enum: [true] },\n\t\t\t},\n\t\t\trequired: ['success'],\n\t\t\tadditionalProperties: false,\n\t\t}),\n\t},\n} as const;\n\nconst dmBlockUserAction = <Path extends string>(_path: Path): TypedAction<typeof dmBlockUserEndpointsProps, Path> =>\n\tasync function action() {\n\t\tconst { roomId, block } = this.bodyParams;\n\t\tconst { room } = await findDirectMessageRoom({ roomId }, this.userId);\n\n\t\tconst blocked = room.uids?.find((uid) => uid !== this.userId);\n\t\tif (!blocked) {\n\t\t\tthrow new Meteor.Error('error-invalid-room', 'Invalid room', { method: 'im.blockUser' });\n\t\t}\n\n\t\tif (block) {\n\t\t\tawait blockUserMethod(this.userId, { rid: room._id, blocked });\n\t\t} else {\n\t\t\tawait unblockUserMethod(this.userId, { rid: room._id, blocked });\n\t\t}\n\n\t\treturn API.v1.success();\n\t};\n\nconst dmEndpoints = API.v1\n\t.post('im.delete', dmDeleteEndpointsProps, dmDeleteAction('im.delete'))\n\t.post('dm.delete', dmDeleteEndpointsProps, dmDeleteAction('dm.delete'))\n\t.post('dm.close', dmCloseEndpointsProps, dmCloseAction('dm.close'))\n\t.post('im.close', dmCloseEndpointsProps, dmCloseAction('im.close'))\n\t.post('dm.create', dmCreateEndpointsProps, dmCreateAction('dm.create'))\n\t.post('im.create', dmCreateEndpointsProps, dmCreateAction('im.create'))","sourceCodeStart":973,"sourceCodeEnd":1009,"githubUrl":"https://github.com/RocketChat/Rocket.Chat/blob/e4b8178b205510181a96ceefee043d0abcd13e5a/apps/meteor/server/api/v1/im.ts#L973-L1009","documentation":"POST /api/v1/im.blockUser resolves the DM room via findDirectMessageRoom, then computes the other participant as room.uids.find((uid) => uid !== this.userId) (im.ts:~983). If no other uid exists the room is not a two-user DM from the caller's perspective - canonically the self-chat DM - so blocking is meaningless and error-invalid-room is thrown with details {method: 'im.blockUser'}. (findDirectMessageRoom throws the same code earlier when the room cannot be resolved at all.)","triggerScenarios":"Calling im.blockUser on your own self-conversation (uids contains only your id, or only duplicates of it); room documents with missing/empty uids after a bad import; calling with a token for a user who is not a participant of the resolved room.","commonSituations":"Clients that render a block action for every room returned by im.list, including the self-DM; moderation scripts iterating all DMs of a user; data-corruption cases where uids was wiped.","solutions":["Guard before calling: skip rooms where room.uids does not contain some uid different from the current user","Hide the block/unblock action entirely for self-chats in the UI","If genuine two-user DMs also fail, audit the room documents' uids array (import or migration damage)"],"exampleFix":"// before\n await api.post('/api/v1/im.blockUser', { roomId, block: true }); // roomId is the self-DM\n\n // after\n const room = rooms.find((r) => r._id === roomId);\n const hasOtherUser = room?.uids?.some((uid) => uid !== currentUserId);\n if (!hasOtherUser) throw new Error('Cannot block: no other participant in this room');\n await api.post('/api/v1/im.blockUser', { roomId, block: true });","handlingStrategy":"validation","validationCode":"const { ims } = await api.get('/api/v1/im.list');\nconst room = ims.find((r) => r._id === roomId);\nconst hasOtherParticipant = (uids: string[] | undefined, me: string) =>\n  Array.isArray(uids) && uids.some((uid) => uid !== me);\nif (!room || !hasOtherParticipant(room.uids, currentUserId)) {\n  throw new Error('Room is not a two-user DM - block/unblock not applicable (self-chat or corrupt uids)');\n}\nawait api.post('/api/v1/im.blockUser', { roomId, block: true });","typeGuard":"const isBlockableDM = (room: { _id: string; uids?: string[] }, currentUserId: string): room is { _id: string; uids: [string, string] } =>\n  !!room.uids && room.uids.some((uid) => uid !== currentUserId);","tryCatchPattern":null,"preventionTips":["Filter self-chat rooms out of any UI that offers block/unblock","Skip rooms whose uids array is missing or contains only the current user before calling im.blockUser/im.unblockUser"],"tags":["rest-api","direct-message","block-user","validation"],"backgroundTag":"invalid-room-state","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"}