RocketChat/Rocket.Chat · error · Error

error-cannot-place-chat-on-hold

Error message

error-cannot-place-chat-on-hold

What it means

Thrown by placeRoomOnHold when `canPlaceChatOnHold` is false. That value is `canRoomBePlacedOnHold && (!restrictedOnHold || canAgentPlaceOnHold)` where restrictedOnHold comes from setting 'Livechat_allow_manual_on_hold_upon_agent_engagement_only' and canAgentPlaceOnHold is `!room.lastMessage?.token` (true when the last message was sent by an agent, false when the visitor sent it). So the error fires when the restrict-on-hold setting is enabled AND the last message in the room came from the visitor.

Source

Thrown at apps/meteor/ee/server/local-services/omnichannel.internalService.ts:54

		this.logger.debug({ msg: 'Attempting to place room on hold', roomId: room._id, userId: onHoldBy?._id });

		const { _id: roomId } = room;

		if (!room || !isOmnichannelRoom(room)) {
			throw new Error('error-invalid-room');
		}
		if (!room.open) {
			throw new Error('error-room-already-closed');
		}
		if (room.onHold) {
			throw new Error('error-room-is-already-on-hold');
		}
		const restrictedOnHold = settings.get('Livechat_allow_manual_on_hold_upon_agent_engagement_only');
		const canRoomBePlacedOnHold = !room.onHold;
		const canAgentPlaceOnHold = !room.lastMessage?.token;
		const canPlaceChatOnHold = canRoomBePlacedOnHold && (!restrictedOnHold || canAgentPlaceOnHold);
		if (!canPlaceChatOnHold) {
			throw new Error('error-cannot-place-chat-on-hold');
		}
		if (!room.servedBy) {
			throw new Error('error-unserved-rooms-cannot-be-placed-onhold');
		}

		const [roomResult, subsResult] = await Promise.all([
			LivechatRooms.setOnHoldByRoomId(roomId),
			Subscriptions.setOnHoldByRoomId(roomId),
			Message.saveSystemMessage<IOmnichannelSystemMessage>('omnichannel_placed_chat_on_hold', roomId, '', onHoldBy, { comment }),
		]);

		if (roomResult.modifiedCount) {
			void notifyOnRoomChangedById(roomId);
		}

		if (subsResult.modifiedCount) {
			void notifyOnSubscriptionChangedByRoomId(roomId);
		}

View on GitHub (pinned to f9d3ec372b)

Solutions

  1. Have the agent send at least one message in the room before attempting to hold it.
  2. If business rules allow holding without engagement, disable 'Livechat_allow_manual_on_hold_upon_agent_engagement_only' in Livechat settings.
  3. In the UI, only enable the Hold button when the last message is from an agent (room.lastMessage?.token is falsy) under that setting.

Example fix

// before
await omnichannelService.placeRoomOnHold(room, comment, user);

// after
const restricted = settings.get('Livechat_allow_manual_on_hold_upon_agent_engagement_only');
if (restricted && room.lastMessage?.token) {
  throw new Error('Reply to the visitor before placing the chat on hold');
}
await omnichannelService.placeRoomOnHold(room, comment, user);
Defensive patterns

Strategy: validation

Validate before calling

const restricted = settings.get('Livechat_allow_manual_on_hold_upon_agent_engagement_only');
if (restricted && room.lastMessage?.token) {
  throw new Error('Reply to the visitor before placing the chat on hold');
}
await omnichannelService.placeRoomOnHold(room, comment, user);

Type guard

function lastMessageFromAgent(room: { lastMessage?: { token?: string } }): boolean {
  return !room.lastMessage?.token;
}

Try / catch

try {
  await omnichannelService.placeRoomOnHold(room, comment, user);
} catch (e) {
  if (e instanceof Error && e.message === 'error-cannot-place-chat-on-hold') {
    notifyUser('Send a reply before placing this chat on hold.');
    return;
  }
  throw e;
}

Prevention

When it happens

Trigger: Settings has 'Livechat_allow_manual_on_hold_upon_agent_engagement_only' enabled, and the agent tries to place the chat on hold before sending any reply (lastMessage.token is set = visitor message). The guard enforces 'agent must have engaged' before a manual hold.

Common situations: Admin enables the engagement-only hold setting; agent opens a chat and immediately hits Hold without replying; visitor's message is the latest in the thread.

Related errors


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