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
- Assign at least one tag to the chat before closing (tag picker in the UI, or options.tags on the close call)
- If the department's chatClosingTags is empty, configure the allowed closing tags on the department
- Disable requestTagBeforeClosingChat on the department when closing tags are not actually required
- 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 enabling requestTagBeforeClosingChat on a department, configure chatClosingTags in the same change
- Wire the close dialog to require a tag whenever the room's department policy is on
- Automated close flows should pass tags in options, or run without clientAction where the policy permits
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
- error-transferring-inquiry
- error-forwarding-chat-same-department
- error-user-not-belong-to-department
- error-contact-not-found
- error-visitor-not-found
AI-assisted analysis of RocketChat/Rocket.Chat@b2c16d5842 (2026-08-18).
Data as JSON: /api/errors/bcdfb646c3486478.
Report an issue: GitHub.