RocketChat/Rocket.Chat · error · Error

error-tags-must-be-assigned-before-closing-chat

error-tags-must-be-assigned-before-closing-chat

Error message

error-tags-must-be-assigned-before-closing-chat

What it means

resolveChatTags enforces the department-level tag policy before closing: if the room's department has requestTagBeforeClosingChat enabled, the close requires that (a) for client-initiated closes (clientAction) the room/options carry at least one tag, and (b) the department has chatClosingTags configured; otherwise Error('error-tags-must-be-assigned-before-closing-chat') is thrown. Rooms without a department, or whose department no longer exists, bypass the check entirely.

Source

Thrown at apps/meteor/server/lib/omnichannel/closeRoom.ts:274

		};
	}

	const { requestTagBeforeClosingChat, chatClosingTags } = department;
	const extraRoomTags = concatUnique(roomTags, chatClosingTags);

	if (!requestTagBeforeClosingChat) {
		return {
			updatedOptions: {
				...options,
				...(extraRoomTags.length && { tags: extraRoomTags }),
			},
		};
	}

	const checkRoomTags = !clientAction || (roomTags && roomTags.length > 0);
	const checkDepartmentTags = chatClosingTags && chatClosingTags.length > 0;
	if (!checkRoomTags || !checkDepartmentTags) {
		throw new Error('error-tags-must-be-assigned-before-closing-chat');
	}

	return {
		updatedOptions: {
			...options,
			...(extraRoomTags.length && { tags: extraRoomTags }),
		},
	};
}

export async function closeOpenChats(userId: string, comment?: string) {
	logger.debug({ msg: 'Closing open chats for user', userId });
	const user = await Users.findOneById(userId);

	const extraQuery = await applyDepartmentRestrictions({}, userId);
	const openChats = LivechatRooms.findOpenByAgent(userId, extraQuery);
	const promises: Promise<void>[] = [];
	await openChats.forEach((room) => {

View on GitHub (pinned to b2c16d5842)

Solutions

  1. Assign at least one tag to the chat before closing (tag picker in the UI, or options.tags on the close call)
  2. If the department's chatClosingTags is empty, configure the allowed closing tags on the department
  3. Disable requestTagBeforeClosingChat on the department when closing tags are not actually required
  4. For server-initiated closes that must not require room tags, invoke the close without clientAction (the room-tag check is then waived, though chatClosingTags must still exist)

Example fix

// before - department requires tags -> throws
await closeRoom({ room, user, comment: 'done' });

// after - supply the required tag
await closeRoom({ room, user, comment: 'done', options: { clientAction: true, tags: ['billing'] } });
Defensive patterns

Strategy: validation

Validate before calling

import { LivechatDepartment } from '@rocket.chat/models';

// before a client-initiated close:
const dept = room.departmentId
  ? await LivechatDepartment.findOneById(room.departmentId, { projection: { requestTagBeforeClosingChat: 1, chatClosingTags: 1 } })
  : null;
if (dept?.requestTagBeforeClosingChat) {
  const hasRoomTags = (room.tags?.length ?? 0) > 0 || (options.tags?.length ?? 0) > 0;
  const hasDeptTags = (dept.chatClosingTags?.length ?? 0) > 0;
  if ((options.clientAction && !hasRoomTags) || !hasDeptTags) {
    // prompt for tags / configure chatClosingTags on the department before closing
  }
}

Try / catch

try {
  await closeRoom({ room, user, options: { clientAction: true, tags: ['billing'] } });
} catch (err: any) {
  if (err?.message === 'error-tags-must-be-assigned-before-closing-chat') return promptForTags(room);
  throw err;
}

Prevention

When it happens

Trigger: Agent closes a chat in a department with requestTagBeforeClosingChat=true without selecting any tag; or the department has the policy on but chatClosingTags was never configured (fails even if the room already has tags); or a programmatic close with clientAction=true and no options.tags.

Common situations: Department admins enable the tag policy without configuring closing tags; custom clients and bulk close flows that never send tags; department configuration incompletely migrated between staging and production.

Related errors


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