{"record":{"id":"b7feea75aa318ca4","repo":"RocketChat/Rocket.Chat","slug":"room-is-blocked","errorCode":null,"errorMessage":"room_is_blocked","messagePattern":"room_is_blocked","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"apps/meteor/server/lib/authorization/canSendMessage.ts","lineNumber":38,"sourceCode":"\textraData?: Record<string, any>,\n): Promise<void> {\n\tif (!room) {\n\t\tthrow new Error('error-invalid-room');\n\t}\n\n\tif (room.archived) {\n\t\tthrow new Error('room_is_archived');\n\t}\n\tif (args.type !== 'app' && !(await canAccessRoomAsync(room, 'uid' in args ? { _id: args.uid } : args, extraData))) {\n\t\tthrow new Error('error-not-allowed');\n\t}\n\n\tif (\n\t\tawait roomCoordinator.getRoomDirectives(room.t).allowMemberAction(room, RoomMemberActions.BLOCK, 'uid' in args ? args.uid : args._id)\n\t) {\n\t\tconst subscription = await Subscriptions.findOneByRoomIdAndUserId(room._id, 'uid' in args ? args.uid : args._id, subscriptionOptions);\n\t\tif (subscription && (subscription.blocked || subscription.blocker)) {\n\t\t\tthrow new Error('room_is_blocked');\n\t\t}\n\t}\n\n\tif (room.ro === true && !(await hasPermissionAsync('uid' in args ? args.uid : args._id, 'post-readonly', room._id))) {\n\t\t// Unless the user was manually unmuted\n\t\tif (args.username && !(room.unmuted || []).includes(args.username)) {\n\t\t\tthrow new Error(\"You can't send messages because the room is readonly.\");\n\t\t}\n\t}\n\n\tif (args.username && room?.muted?.includes(args.username)) {\n\t\tthrow new Error('You_have_been_muted');\n\t}\n}\n// TODO: remove option uid and username and type\nexport async function canSendMessageAsync(\n\trid: IRoom['_id'],\n\tuser: { uid: IUser['_id']; username: IUser['username']; type: IUser['type'] } | IUser,","sourceCodeStart":20,"sourceCodeEnd":56,"githubUrl":"https://github.com/RocketChat/Rocket.Chat/blob/b2c16d5842cbe6b69b59bdf6fc5e5f1afcd1f0b0/apps/meteor/server/lib/authorization/canSendMessage.ts#L20-L56","documentation":"When the room type's directives allow the BLOCK member action (direct messages do), validateRoomMessagePermissionsAsync throws room_is_blocked (plain Error) if the caller's subscription has blocked or blocker set — i.e. a DM where either participant blocked the other. Rocket.Chat stores that state on the DM subscription document.","triggerScenarios":"sendMessage in a direct-message room where subscription.blocked (you blocked them) or subscription.blocker (they blocked you) is set — typically an automation reusing a stale DM rid after a block happened.","commonSituations":"A user blocks a contact and an old bot/automation still tries to DM them; both directions of a DM break for integrations when either side blocks; background jobs iterate all DMs without filtering blocked ones.","solutions":["Unblock the user (user card -> unblock), which clears the blocked/blocker flags on the DM subscription","Route the automation through a normal channel instead of the blocked DM","Before sending programmatically, inspect the subscription (Subscriptions.findOneByRoomIdAndUserId with projection { blocked: 1, blocker: 1 }) and skip blocked DMs"],"exampleFix":null,"handlingStrategy":"validation","validationCode":"const sub = await Subscriptions.findOneByRoomIdAndUserId(rid, uid, { projection: { blocked: 1, blocker: 1 } });\nif (sub?.blocked || sub?.blocker) {\n  // DM is blocked in one or both directions: skip the send and report 'blocked'\n}","typeGuard":"const isBlockedSubscription = (s: { blocked?: boolean; blocker?: boolean } | null | undefined): boolean =>\n  s?.blocked === true || s?.blocker === true;","tryCatchPattern":"try {\n  await sendMessage(...);\n} catch (e) {\n  if (e instanceof Error && e.message === 'room_is_blocked') {\n    // a participant blocked the other: do not retry; offer unblock or another channel\n  }\n  throw e;\n}","preventionTips":["In DM automations, check the subscription flags before each send","Prefer posting as a bot added to a shared channel over DMs","Treat blocked DMs as a normal state, not an error, in bulk messaging jobs"],"tags":["authorization","direct-messages","blocking","subscriptions"],"backgroundTag":"user-blocked-dm","analyzedSha":"b2c16d5842cbe6b69b59bdf6fc5e5f1afcd1f0b0","analyzedAt":"2026-08-18T15:26:39.429Z","schemaVersion":2},"datasetVersion":"2026-08-21T18:17:14.833Z"}