{"record":{"id":"25e317b901d4e30f","repo":"RocketChat/Rocket.Chat","slug":"error-unit-not-found","errorCode":"error-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":111,"sourceCode":"\n\t\tcheck(unitDepartments, [\n\t\t\tMatch.ObjectIncluding({\n\t\t\t\tdepartmentId: String,\n\t\t\t}),\n\t\t]);\n\n\t\tlet ancestors: string[] = [];\n\t\tif (_id) {\n\t\t\tconst unitsFromUser = await getUnitsFromUser(userId);\n\t\t\tconst unit = await LivechatUnit.findOneById<Pick<IOmnichannelBusinessUnit, '_id' | 'ancestors'>>(\n\t\t\t\t_id,\n\t\t\t\t{\n\t\t\t\t\tprojection: { _id: 1, ancestors: 1 },\n\t\t\t\t},\n\t\t\t\t{ unitsFromUser },\n\t\t\t);\n\t\t\tif (!unit) {\n\t\t\t\tthrow new Meteor.Error('error-unit-not-found', 'Unit not found', {\n\t\t\t\t\tmethod: 'livechat:saveUnit',\n\t\t\t\t});\n\t\t\t}\n\n\t\t\tancestors = unit.ancestors || [];\n\t\t}\n\n\t\tconst validUserMonitors = await Users.findUsersInRolesWithQuery(\n\t\t\t'livechat-monitor',\n\t\t\t{ _id: { $in: unitMonitors.map(({ monitorId }) => monitorId) } },\n\t\t\t{ projection: { _id: 1, username: 1 } },\n\t\t).toArray();\n\n\t\tconst monitors = validUserMonitors.map(({ _id: monitorId, username }) => ({\n\t\t\tmonitorId,\n\t\t\tusername: username!,\n\t\t}));\n","sourceCodeStart":93,"sourceCodeEnd":129,"githubUrl":"https://github.com/RocketChat/Rocket.Chat/blob/f9d3ec372bb580fa8d036f94cf03925a478ef768/apps/meteor/ee/server/lib/omnichannel/LivechatEnterprise.ts#L93-L129","documentation":"Thrown by saveUnit in LivechatEnterprise.ts:111 when editing an existing business unit (_id supplied) but the unit cannot be found within the caller's scoped set (unitsFromUser). It is a guard before reading ancestors for the update. Code is 'error-unit-not-found' (note the different prefix from 240) via Meteor.Error with method 'livechat:saveUnit'.","triggerScenarios":"Calling livechat:saveUnit with a stale _id after the unit was deleted, or with a userId not assigned as a monitor of that unit. The scoped findOne (unitsFromUser) returns null even if the unit exists globally.","commonSituations":"Editing a business unit in a long-open form whose row was removed elsewhere; cross-tenant / cross-unit admin editing a unit they do not monitor; race between saveUnit and removeUnit.","solutions":["Re-fetch the unit list for the current userId and use a fresh _id.","Confirm the user is assigned as a monitor of the target unit before allowing edit.","Catch Meteor.Error 'error-unit-not-found' and surface a 'unit no longer available' message rather than retrying blindly."],"exampleFix":"// before\nawait saveUnit(_id, unitData, monitors, depts, userId);\n\n// after\nconst mine = await getUnitsFromUser(userId);\nif (!_id || !mine.includes(_id)) {\n  throw new Error('refresh unit list; _id not in user scope');\n}\nawait saveUnit(_id, unitData, monitors, depts, userId);","handlingStrategy":"validation","validationCode":"if (_id) {\n  const mine = await getUnitsFromUser(userId);\n  const unit = await LivechatUnit.findOneById(_id, { projection: { _id: 1 } }, { unitsFromUser: mine });\n  if (!unit) throw new Error('refresh; unit not in scope');\n}","typeGuard":"const canEditUnit = async (_id: string, userId: string): Promise<boolean> => {\n  const mine = await getUnitsFromUser(userId);\n  return Boolean(await LivechatUnit.findOneById(_id, { projection: { _id: 1 } }, { unitsFromUser: mine }));\n};","tryCatchPattern":"try { await saveUnit(_id, unitData, monitors, depts, userId); }\ncatch (e) {\n  if (e instanceof Meteor.Error && e.error === 'error-unit-not-found') { /* refresh UI */ return; }\n  throw e;\n}","preventionTips":["Confirm the user is a monitor of the target unit before opening the edit form.","Refetch the unit when the form gains focus."],"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"}