RocketChat/Rocket.Chat · error · Meteor.Error

unit-not-found

unit-not-found

Error message

Unit not found

What it means

removeUnit deletes a business unit scoped to the units the executing user may see (getUnitsFromUser). If no document matched both the given _id and that scope, deletedCount is 0 and it throws unit-not-found for method livechat:removeUnit.

Solutions

  1. Re-fetch the current units list and retry with the existing id
  2. Verify the caller has visibility of the unit (getUnitsFromUser scope) or use an unrestricted admin
  3. If it was already deleted, no action is needed
Defensive patterns

Strategy: try-catch

Validate before calling

const unit = await LivechatUnit.findOneById(_id);
if (!unit) {
	// unit already gone; treat removal as done
}
await LivechatEnterprise.removeUnit(_id, userId);

Try / catch

try {
	await LivechatEnterprise.removeUnit(_id, userId);
} catch (err) {
	if ((err as Meteor.Error)?.error === 'unit-not-found') {
		// refresh list; if caller scope hid it, retry as unrestricted admin
	} else {
		throw err;
	}
}

Prevention

When it happens

Trigger: Calling livechat:removeUnit with a wrong or stale unit id, or with a unit that exists but is outside the caller's allowed units.

Common situations: UI holding a stale list after the unit was removed in another session; admin with unit-scoped visibility trying to remove a unit they cannot see; double-submit.

Understand the failure class

Background: 'Could not be found', 'does not exist', 'not found in database': the resource-not-found family when an ID, slug, key, or URI lookup comes back empty — this error's family across 20 libraries.

Related errors


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

Appendix: source

Thrown at apps/meteor/ee/server/lib/omnichannel/LivechatEnterprise.ts:63

		if (!(await removeUserFromRolesAsync(user._id, ['livechat-monitor']))) {
			return false;
		}

		// remove this monitor from any unit it is assigned to
		await LivechatUnitMonitors.removeByMonitorId(user._id);

		return true;
	},

	async removeUnit(_id: string, userId: string) {
		check(_id, String);

		const unitsFromUser = await getUnitsFromUser(userId);

		const result = await LivechatUnit.removeByIdAndUnit(_id, unitsFromUser);
		if (!result.deletedCount) {
			throw new Meteor.Error('unit-not-found', 'Unit not found', { method: 'livechat:removeUnit' });
		}

		return result;
	},

	async saveUnit(
		_id: string | null,
		unitData: Omit<IOmnichannelBusinessUnit, '_id'>,
		unitMonitors: { monitorId: string; username: string },
		unitDepartments: { departmentId: string }[],
		userId: string,
	) {
		check(_id, Match.Maybe(String));

		check(unitData, {
			name: String,
			visibility: String,
			enabled: Match.Optional(Boolean),

View on GitHub (pinned to b2c16d5842)