RocketChat/Rocket.Chat · error · Meteor.Error
unit-not-found
unit-not-found
Error message
Unit not found
What it means
Thrown by removeUnit in LivechatEnterprise.ts:63 when a business-unit deletion affects zero documents. The handler first narrows the allowed set to units the operator is permitted to manage (getUnitsFromUser), then deletes by _id AND that scope; if neither the _id nor any scoped unit matches, deletedCount is 0. This is a Meteor.Error, so the code 'unit-not-found' and the {method:'livechat:removeUnit'} detail travel to the client.
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 f9d3ec372b)
Solutions
- Refresh the business-unit list and confirm the _id still exists for the current user before retrying.
- Verify the calling userId actually appears in getUnitsFromUser for that unit (permissions/monitor assignment).
- Handle the meteor error by code 'unit-not-found' and treat it as already-gone (idempotent success) if appropriate.
Example fix
// before
await removeUnit(_id, userId);
// after
try {
await removeUnit(_id, userId);
} catch (e) {
if (e instanceof Meteor.Error && e.error === 'unit-not-found') {
// already removed; refresh list and continue
return;
}
throw e;
} Defensive patterns
Strategy: try-catch
Validate before calling
const mine = await getUnitsFromUser(userId);
const exists = mine.includes(_id);
// or: await LivechatUnit.findOneById(_id, { projection: { _id: 1 } }, { unitsFromUser: mine }); Type guard
const isUnitRemovable = async (_id: string, userId: string): Promise<boolean> => {
const mine = await getUnitsFromUser(userId);
return mine.includes(_id);
}; Try / catch
try { await removeUnit(_id, userId); }
catch (e) {
if (e instanceof Meteor.Error && e.error === 'unit-not-found') return; // idempotent
throw e;
} Prevention
- Refresh the unit list before delete actions.
- Disable the delete button after first click.
When it happens
Trigger: Calling livechat:removeUnit with an _id that does not exist, or with a userId whose getUnitsFromUser set does not contain that unit (e.g. an omnichannel manager scoped to other business units). Also fires if the unit was concurrently deleted between lookup and removal.
Common situations: UI list went stale and the row was already removed; user belongs to a different business unit than the one they are trying to delete; test fixtures did not seed the unit for that userId; multi-tab scenario where another admin removed it first.
Related errors
- error-unit-not-found
- error-unit-not-found
- error-not-authorized-federation
- error-forwarding-department-target-not-allowed
- error-invalid-sla
AI-assisted analysis of RocketChat/Rocket.Chat@f9d3ec372b (2026-08-12).
Data as JSON: /api/errors/f57af31522618755.
Report an issue: GitHub.