{"record":{"id":"f57af31522618755","repo":"RocketChat/Rocket.Chat","slug":"unit-not-found","errorCode":"unit-not-found","errorMessage":"Unit not found","messagePattern":"Unit not found","errorType":"exception","errorClass":"Meteor.Error","httpStatus":null,"severity":"error","filePath":"apps/meteor/ee/server/lib/omnichannel/LivechatEnterprise.ts","lineNumber":63,"sourceCode":"\n\t\tif (!(await removeUserFromRolesAsync(user._id, ['livechat-monitor']))) {\n\t\t\treturn false;\n\t\t}\n\n\t\t// remove this monitor from any unit it is assigned to\n\t\tawait LivechatUnitMonitors.removeByMonitorId(user._id);\n\n\t\treturn true;\n\t},\n\n\tasync removeUnit(_id: string, userId: string) {\n\t\tcheck(_id, String);\n\n\t\tconst unitsFromUser = await getUnitsFromUser(userId);\n\n\t\tconst result = await LivechatUnit.removeByIdAndUnit(_id, unitsFromUser);\n\t\tif (!result.deletedCount) {\n\t\t\tthrow new Meteor.Error('unit-not-found', 'Unit not found', { method: 'livechat:removeUnit' });\n\t\t}\n\n\t\treturn result;\n\t},\n\n\tasync saveUnit(\n\t\t_id: string | null,\n\t\tunitData: Omit<IOmnichannelBusinessUnit, '_id'>,\n\t\tunitMonitors: { monitorId: string; username: string },\n\t\tunitDepartments: { departmentId: string }[],\n\t\tuserId: string,\n\t) {\n\t\tcheck(_id, Match.Maybe(String));\n\n\t\tcheck(unitData, {\n\t\t\tname: String,\n\t\t\tvisibility: String,\n\t\t\tenabled: Match.Optional(Boolean),","sourceCodeStart":45,"sourceCodeEnd":81,"githubUrl":"https://github.com/RocketChat/Rocket.Chat/blob/f9d3ec372bb580fa8d036f94cf03925a478ef768/apps/meteor/ee/server/lib/omnichannel/LivechatEnterprise.ts#L45-L81","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","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."],"exampleFix":"// before\nawait removeUnit(_id, userId);\n\n// after\ntry {\n  await removeUnit(_id, userId);\n} catch (e) {\n  if (e instanceof Meteor.Error && e.error === 'unit-not-found') {\n    // already removed; refresh list and continue\n    return;\n  }\n  throw e;\n}","handlingStrategy":"try-catch","validationCode":"const mine = await getUnitsFromUser(userId);\nconst exists = mine.includes(_id);\n// or: await LivechatUnit.findOneById(_id, { projection: { _id: 1 } }, { unitsFromUser: mine });","typeGuard":"const isUnitRemovable = async (_id: string, userId: string): Promise<boolean> => {\n  const mine = await getUnitsFromUser(userId);\n  return mine.includes(_id);\n};","tryCatchPattern":"try { await removeUnit(_id, userId); }\ncatch (e) {\n  if (e instanceof Meteor.Error && e.error === 'unit-not-found') return; // idempotent\n  throw e;\n}","preventionTips":["Refresh the unit list before delete actions.","Disable the delete button after first click."],"tags":["omnichannel","business-unit","permissions","meteor-error"],"backgroundTag":null,"analyzedSha":"f9d3ec372bb580fa8d036f94cf03925a478ef768","analyzedAt":"2026-08-12T19:07:17.372Z","schemaVersion":2},"datasetVersion":"2026-08-12T23:17:12.415Z"}