RocketChat/Rocket.Chat · error · Error

error-failed-to-delete-department

error-failed-to-delete-department

Error message

error-failed-to-delete-department

What it means

Thrown by `removeDepartment` when `LivechatDepartment.removeById(_id)` returns a write result with `acknowledged !== true`. This is a MongoDB driver-level outcome: the deleteOne was not acknowledged by the server (unacknowledged write concern, connection drop mid-write, or driver error surfaced through the result rather than an exception).

Source

Thrown at apps/meteor/server/lib/omnichannel/departmentsLib.ts:225

	// Visitor is already validated at this point
	return LivechatVisitors.updateDepartmentById(visitorId, department);
}

export async function removeDepartment(departmentId: string) {
	livechatLogger.debug({ msg: 'Removing department', departmentId });

	const department = await LivechatDepartment.findOneById<Pick<ILivechatDepartment, '_id' | 'businessHourId' | 'parentId'>>(departmentId, {
		projection: { _id: 1, businessHourId: 1, parentId: 1 },
	});
	if (!department) {
		throw new Error('error-department-not-found');
	}

	const { _id } = department;

	const ret = await LivechatDepartment.removeById(_id);
	if (ret.acknowledged !== true) {
		throw new Error('error-failed-to-delete-department');
	}

	const removedAgents = await LivechatDepartmentAgents.findByDepartmentId(department._id, { projection: { agentId: 1 } }).toArray();

	const actions = ['Removing department agents', 'Unsetting fallback department', 'Removing department from rooms'];
	livechatLogger.debug({
		msg: 'Post department removal actions',
		departmentId: _id,
		actions,
	});

	const promiseResponses = await Promise.allSettled([
		LivechatDepartmentAgents.removeByDepartmentId(_id),
		LivechatDepartment.unsetFallbackDepartmentByDepartmentId(_id),
		LivechatRooms.bulkRemoveDepartmentAndUnitsFromRooms(_id),
	]);

	promiseResponses.forEach((response, index) => {

View on GitHub (pinned to b2c16d5842)

Solutions

  1. Retry `removeDepartment` after verifying the department still exists (the delete may or may not have landed)
  2. Check MongoDB health and write concern configuration (avoid w:0 for control-plane writes)
  3. Inspect server logs/mongod for the write outcome; if the document persists, retry usually succeeds once the connection stabilizes

Example fix

// before
await removeDepartment(depId);

// after
for (let attempt = 1; attempt <= 3; attempt++) {
  try {
    await removeDepartment(depId);
    break;
  } catch (e) {
    if (e.message !== 'error-failed-to-delete-department' || attempt === 3) throw e;
    await LivechatDepartment.findOneById(depId, { projection: { _id: 1 } }).then((d) => !d && break);
  }
}
Defensive patterns

Strategy: retry

Validate before calling

// Not a payload problem — pre-check connection health instead
const ping = await LivechatDepartment.findOneById(depId, { projection: { _id: 1 } });
if (!ping) return; // already gone — nothing to delete

Try / catch

let lastErr: unknown;
for (let i = 0; i < 3; i++) {
  try {
    await removeDepartment(depId);
    lastErr = undefined;
    break;
  } catch (e) {
    if (e instanceof Error && e.message !== 'error-failed-to-delete-department') throw e;
    lastErr = e;
  }
}
if (lastErr) throw lastErr;

Prevention

When it happens

Trigger: MongoDB connection instability at the moment of the delete, a write concern configured without acknowledgement (w: 0), or a driver/server version quirk returning acknowledged:false — the department lookup succeeded, so the document existed an instant earlier.

Common situations: Self-hosted MongoDB behind flaky networking; replica set step-down during the delete; aggressive connection-pool recycling; custom write-concern settings.

Related errors


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