RocketChat/Rocket.Chat · error
room_is_archived
Error message
room_is_archived
What it means
validateRoomMessagePermissionsAsync throws room_is_archived (plain Error) when room.archived is true — and it does so before any access or permission checks. Archived channels are frozen: nobody can send messages, regardless of role or permission.
Source
Thrown at apps/meteor/server/lib/authorization/canSendMessage.ts:27
const subscriptionOptions = {
projection: {
blocked: 1,
blocker: 1,
},
};
// TODO: remove option uid and username and type
export async function validateRoomMessagePermissionsAsync(
room: IRoom | null,
args: { uid: IUser['_id']; username: IUser['username']; type: IUser['type'] } | IUser,
extraData?: Record<string, any>,
): Promise<void> {
if (!room) {
throw new Error('error-invalid-room');
}
if (room.archived) {
throw new Error('room_is_archived');
}
if (args.type !== 'app' && !(await canAccessRoomAsync(room, 'uid' in args ? { _id: args.uid } : args, extraData))) {
throw new Error('error-not-allowed');
}
if (
await roomCoordinator.getRoomDirectives(room.t).allowMemberAction(room, RoomMemberActions.BLOCK, 'uid' in args ? args.uid : args._id)
) {
const subscription = await Subscriptions.findOneByRoomIdAndUserId(room._id, 'uid' in args ? args.uid : args._id, subscriptionOptions);
if (subscription && (subscription.blocked || subscription.blocker)) {
throw new Error('room_is_blocked');
}
}
if (room.ro === true && !(await hasPermissionAsync('uid' in args ? args.uid : args._id, 'post-readonly', room._id))) {
// Unless the user was manually unmuted
if (args.username && !(room.unmuted || []).includes(args.username)) {
throw new Error("You can't send messages because the room is readonly.");View on GitHub (pinned to b2c16d5842)
Solutions
- Unarchive the channel (Administration -> Rooms, or owner actions) if posting should resume
- Retire or redirect integrations/webhooks that target archived channels
- Handle room_is_archived in clients by switching the room to a read-only 'archived' state instead of retrying
Defensive patterns
Strategy: validation
Validate before calling
if (room.archived) {
// mark the channel as archived in the client and stop; do not call send
} Type guard
const isArchivedRoom = (room: { archived?: boolean }): boolean => room.archived === true; Try / catch
try {
await sendMessage(...);
} catch (e) {
if (e instanceof Error && e.message === 'room_is_archived') {
// permanent until unarchived: show archived state, disable composer
}
throw e;
} Prevention
- Reflect room.archived in the client UI (disable composer) as soon as the room is loaded
- Unsubscribe/repoint webhooks when archiving channels
- Include archived channels in integration lifecycle checks
When it happens
Trigger: sendMessage / chat.postMessage / UI send targeting a channel that was archived by its owner or an admin, including webhooks and integrations still pointed at the archived channel.
Common situations: Webhooks keep posting to a channel archived at project end; clients hold a stale cached room list and let users type into archived channels; users do not notice the archived banner.
Related errors
- error-not-allowed
- Message converter not found
- error-not-authorized
- error-not-allowed
- error-room-archived
AI-assisted analysis of RocketChat/Rocket.Chat@b2c16d5842 (2026-08-18).
Data as JSON: /api/errors/e6b314f1f3e18e94.
Report an issue: GitHub.