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

  1. Unarchive the channel (Administration -> Rooms, or owner actions) if posting should resume
  2. Retire or redirect integrations/webhooks that target archived channels
  3. 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

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


AI-assisted analysis of RocketChat/Rocket.Chat@b2c16d5842 (2026-08-18). Data as JSON: /api/errors/e6b314f1f3e18e94. Report an issue: GitHub.