RocketChat/Rocket.Chat · error
You can't delete messages because the room is readonly.
Error message
You can't delete messages because the room is readonly.
What it means
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.
Source
Thrown at apps/meteor/server/lib/authorization/canDeleteMessage.ts:72
allowedToDeleteAny || (deletingUser._id === u._id && (await hasPermissionAsync(deletingUser._id, 'delete-own-message', rid)));
if (!allowed) {
return false;
}
const bypassBlockTimeLimit = await hasPermissionAsync(deletingUser._id, 'bypass-time-limit-edit-and-delete', rid);
if (!bypassBlockTimeLimit) {
const blockDeleteInMinutes = await getValue('Message_AllowDeleting_BlockDeleteInMinutes');
if (blockDeleteInMinutes) {
const timeElapsedForMessage = elapsedTime(ts);
return timeElapsedForMessage <= blockDeleteInMinutes;
}
}
if (room.ro === true && !(await hasPermissionAsync(deletingUser._id, 'post-readonly', rid))) {
// Unless the user was manually unmuted
if (deletingUser.username && !(room.unmuted || []).includes(deletingUser.username)) {
throw new Error("You can't delete messages because the room is readonly.");
}
}
return true;
};
View on GitHub (pinned to b2c16d5842)
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
Defensive patterns
Strategy: try-catch
Validate before calling
const canDeleteInRoom =
room.ro !== true ||
(await hasPermissionAsync(uid, 'post-readonly', room._id)) ||
(room.unmuted || []).includes(username);
if (!canDeleteInRoom) {
// skip the delete call and inform the user instead of letting the server throw
} Try / catch
try {
await deleteMessageAsync(...);
} catch (e) {
if (e instanceof Error && e.message.includes('room is readonly')) {
// plain Error, not Meteor.Error: match the message; show 'deletion blocked in read-only channel'
}
throw e;
} Prevention
- 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
When it happens
Trigger: 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.
Common situations: 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.
Related errors
- You can't send messages because the room is readonly.
- error-action-not-allowed
- Not_authorized
- error-not-authorized-federation
- error-not-authorized
AI-assisted analysis of RocketChat/Rocket.Chat@b2c16d5842 (2026-08-18).
Data as JSON: /api/errors/bbe1a8ec55ef24a8.
Report an issue: GitHub.