{"record":{"id":"bbe1a8ec55ef24a8","repo":"RocketChat/Rocket.Chat","slug":"you-can-t-delete-messages-because-the-room-is-read","errorCode":null,"errorMessage":"You can't delete messages because the room is readonly.","messagePattern":"You can't delete messages because the room is readonly\\.","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"apps/meteor/server/lib/authorization/canDeleteMessage.ts","lineNumber":72,"sourceCode":"\t\tallowedToDeleteAny || (deletingUser._id === u._id && (await hasPermissionAsync(deletingUser._id, 'delete-own-message', rid)));\n\tif (!allowed) {\n\t\treturn false;\n\t}\n\tconst bypassBlockTimeLimit = await hasPermissionAsync(deletingUser._id, 'bypass-time-limit-edit-and-delete', rid);\n\n\tif (!bypassBlockTimeLimit) {\n\t\tconst blockDeleteInMinutes = await getValue('Message_AllowDeleting_BlockDeleteInMinutes');\n\n\t\tif (blockDeleteInMinutes) {\n\t\t\tconst timeElapsedForMessage = elapsedTime(ts);\n\t\t\treturn timeElapsedForMessage <= blockDeleteInMinutes;\n\t\t}\n\t}\n\n\tif (room.ro === true && !(await hasPermissionAsync(deletingUser._id, 'post-readonly', rid))) {\n\t\t// Unless the user was manually unmuted\n\t\tif (deletingUser.username && !(room.unmuted || []).includes(deletingUser.username)) {\n\t\t\tthrow new Error(\"You can't delete messages because the room is readonly.\");\n\t\t}\n\t}\n\n\treturn true;\n};\n","sourceCodeStart":54,"sourceCodeEnd":78,"githubUrl":"https://github.com/RocketChat/Rocket.Chat/blob/b2c16d5842cbe6b69b59bdf6fc5e5f1afcd1f0b0/apps/meteor/server/lib/authorization/canDeleteMessage.ts#L54-L78","documentation":"canDeleteMessageAsync throws this plain Error (not a Meteor.Error) when the room is read-only (room.ro === true), the user lacks the 'post-readonly' permission in that room, and their username is not in room.unmuted. Read-only rooms only allow deletions by users who may still post there. Because it is a plain Error, method/REST callers see it as an internal error and must match on the message string.","triggerScenarios":"Deleting a message (UI delete, chat.delete) in a read-only channel as a user without post-readonly permission who has not been unmuted by a moderator.","commonSituations":"Announcement channels set read-only; users holding 'delete-own-message' permission still cannot delete in read-only rooms because delete capability there rides on post-readonly; moderators unmute speakers for posting but forget deletions need the same unmute.","solutions":["Grant the role 'post-readonly' permission (Administration -> Permissions) so the user may act in read-only rooms","Unmute the specific user in the read-only channel (adds their username to room.unmuted)","Turn off read-only for the channel if deletion should be allowed","In server code note the earlier branch: when Message_AllowDeleting_BlockDeleteInMinutes is set the function returns false instead of throwing — handle both outcomes"],"exampleFix":null,"handlingStrategy":"try-catch","validationCode":"const canDeleteInRoom =\n  room.ro !== true ||\n  (await hasPermissionAsync(uid, 'post-readonly', room._id)) ||\n  (room.unmuted || []).includes(username);\nif (!canDeleteInRoom) {\n  // skip the delete call and inform the user instead of letting the server throw\n}","typeGuard":null,"tryCatchPattern":"try {\n  await deleteMessageAsync(...);\n} catch (e) {\n  if (e instanceof Error && e.message.includes('room is readonly')) {\n    // plain Error, not Meteor.Error: match the message; show 'deletion blocked in read-only channel'\n  }\n  throw e;\n}","preventionTips":["Hide/disable delete actions in the UI when room.ro is set and the user lacks post-readonly","Remember delete rights in read-only rooms ride on post-readonly, not delete permissions","When moderating read-only channels, unmute users who must clean up their own messages"],"tags":["authorization","messages","readonly-room","permissions"],"backgroundTag":"readonly-room-write-denied","analyzedSha":"b2c16d5842cbe6b69b59bdf6fc5e5f1afcd1f0b0","analyzedAt":"2026-08-18T15:26:39.429Z","schemaVersion":2},"datasetVersion":"2026-08-21T13:17:26.733Z"}