RocketChat/Rocket.Chat · warning · Error

Department ${departmentData._id} not found

Error message

Department ${departmentData._id} not found

What it means

Thrown by the IPostLivechatDepartmentDisabled case in livechatEvent when the departments converter's convertDepartment returns null for the supplied departmentData. The bridge will not dispatch the department-disabled event to Apps because the department object could not be converted. This typically means the department record referenced by departmentData._id is inconsistent or already gone.

Source

Thrown at apps/meteor/app/apps/server/bridges/listeners.ts:491

				const [roomId] = args.payload;
				const room = await this.orch.getConverters().get('rooms').convertById(roomId);

				if (!room) {
					throw new Error(`Room with id ${roomId} not found`);
				}

				return this.orch
					.getManager()
					.getListenerManager()
					.executeListener(args.event, room as IAppsLivechatRoom);
			}

			case AppInterface.IPostLivechatDepartmentDisabled: {
				const [departmentData] = args.payload;
				const department = await this.orch.getConverters().get('departments').convertDepartment(departmentData);

				if (!department) {
					throw new Error(`Department ${departmentData._id} not found`);
				}

				return this.orch.getManager().getListenerManager().executeListener(args.event, { department });
			}

			case AppInterface.IPostLivechatDepartmentRemoved: {
				const [departmentData] = args.payload;
				const department = await this.orch.getConverters().get('departments').convertDepartment(departmentData);

				if (!department) {
					throw new Error(`Department ${departmentData._id} not found`);
				}

				return this.orch.getManager().getListenerManager().executeListener(args.event, { department });
			}

			default:
				const [roomData] = args.payload;

View on GitHub (pinned to f9d3ec372b)

Solutions

  1. Check that the department identified by departmentData._id still exists in LivechatDepartment at processing time.
  2. If disable and remove are issued back-to-back, serialize them so the disabled event drains before removal.
  3. Verify the department payload dispatched to the event matches the current LivechatDepartment schema.
  4. On version upgrades, confirm the departments converter and LivechatDepartment model are from the same release.
Defensive patterns

Strategy: try-catch

Validate before calling

const dept = await LivechatDepartment.findOneById(departmentData._id);
if (!dept) {
  return; // do not emit IPostLivechatDepartmentDisabled
}
await emitEvent(AppInterface.IPostLivechatDepartmentDisabled, { payload: [departmentData] });

Type guard

const isPersistedDepartment = async (id: string): Promise<boolean> => {
  return Boolean(await LivechatDepartment.findOneById(id, { projection: { _id: 1 } }));
};

Try / catch

try {
  await listenerManager.executeListener(args.event, { department });
} catch (e) {
  this.orch.debugLog(`Skipping ${args.event}: ${(e as Error).message}`);
}

Prevention

When it happens

Trigger: Server emits IPostLivechatDepartmentDisabled carrying a departmentData payload; convertDepartment(departmentData) resolves falsy, e.g. the underlying LivechatDepartment document was removed, the document shape changed in a version mismatch, or the converter's internal lookup by departmentData._id returns nothing.

Common situations: A department is removed immediately after being disabled (disable-then-remove in quick succession); a schema/typing drift between the apps-engine IDepartment and the persisted document; a custom omnichannel migration that strips departments; partial department data passed to the event.

Related errors


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