{"record":{"id":"23b200dfec057cc8","repo":"RocketChat/Rocket.Chat","slug":"error-fallback-department-circular","errorCode":"error-fallback-department-circular","errorMessage":"Cannot save department. Circular reference between fallback department and department","messagePattern":"Cannot save department\\. Circular reference between fallback department and department","errorType":"error_code","errorClass":"Meteor.Error","httpStatus":null,"severity":"error","filePath":"apps/meteor/server/lib/omnichannel/departmentsLib.ts","lineNumber":110,"sourceCode":"\t);\n\n\tconst { requestTagBeforeClosingChat, chatClosingTags, fallbackForwardDepartment } = departmentData;\n\tif (requestTagBeforeClosingChat && (!chatClosingTags || chatClosingTags.length === 0)) {\n\t\tthrow new Meteor.Error(\n\t\t\t'error-validating-department-chat-closing-tags',\n\t\t\t'At least one closing tag is required when the department requires tag(s) on closing conversations.',\n\t\t\t{ method: 'livechat:saveDepartment' },\n\t\t);\n\t}\n\n\tif (_id && !department) {\n\t\tthrow new Meteor.Error('error-department-not-found', 'Department not found', {\n\t\t\tmethod: 'livechat:saveDepartment',\n\t\t});\n\t}\n\n\tif (fallbackForwardDepartment === _id) {\n\t\tthrow new Meteor.Error(\n\t\t\t'error-fallback-department-circular',\n\t\t\t'Cannot save department. Circular reference between fallback department and department',\n\t\t);\n\t}\n\n\tif (fallbackForwardDepartment) {\n\t\tconst fallbackDep = await LivechatDepartment.findOneById<Pick<ILivechatDepartment, '_id'>>(fallbackForwardDepartment, {\n\t\t\tprojection: { _id: 1 },\n\t\t});\n\t\tif (!fallbackDep) {\n\t\t\tthrow new Meteor.Error('error-fallback-department-not-found', 'Fallback department not found', {\n\t\t\t\tmethod: 'livechat:saveDepartment',\n\t\t\t});\n\t\t}\n\t}\n\n\tconst departmentDB = await LivechatDepartment.createOrUpdateDepartment(_id, departmentData);\n\tif (departmentDB && departmentAgents) {","sourceCodeStart":92,"sourceCodeEnd":128,"githubUrl":"https://github.com/RocketChat/Rocket.Chat/blob/b2c16d5842cbe6b69b59bdf6fc5e5f1afcd1f0b0/apps/meteor/server/lib/omnichannel/departmentsLib.ts#L92-L128","documentation":"Thrown by `livechat:saveDepartment` when `fallbackForwardDepartment` (the department that receives chats when this one is unavailable) equals the department's own `_id`. A self-referencing fallback would loop a stranded chat back to the same unavailable department, so the save is rejected before persistence.","triggerScenarios":"The department edit form pre-populates the fallback dropdown with the department itself and the user leaves it selected; or an API client builds the payload with `fallbackForwardDepartment: _id` by default when no other fallback is chosen.","commonSituations":"Default-select behavior in custom dropdowns; scripted bulk edits that set fallback to the department's own id; misunderstanding the field as 'primary department' rather than 'fallback target'.","solutions":["Pick a different department as fallback, or clear the field entirely (falsy fallbackForwardDepartment skips both the circular and existence checks)","Fix form logic so a department is never offered as its own fallback option"],"exampleFix":"// before\nawait saveDepartment(_id, { ...data, fallbackForwardDepartment: _id });\n\n// after\nconst payload = { ...data };\nif (payload.fallbackForwardDepartment === _id) {\n  delete payload.fallbackForwardDepartment;\n}\nawait saveDepartment(_id, payload);","handlingStrategy":"validation","validationCode":"if (deptData.fallbackForwardDepartment && deptData.fallbackForwardDepartment === _id) {\n  delete deptData.fallbackForwardDepartment; // or reject with a clear message\n}\nawait saveDepartment(_id, deptData);","typeGuard":"const hasCircularFallback = (_id: string, fallback?: string): boolean =>\n  fallback != null && fallback === _id;","tryCatchPattern":"try {\n  await saveDepartment(_id, deptData);\n} catch (e) {\n  if (isMeteorError(e, 'error-fallback-department-circular')) {\n    // clear the fallback selection and re-save\n  }\n}","preventionTips":["Exclude the current department from its own fallback dropdown options","Assert fallback !== self in API clients before sending","Treat fallback as optional: omit rather than default to self"],"tags":["omnichannel","departments","circular-reference","fallback","validation"],"backgroundTag":"circular-reference-detected","analyzedSha":"b2c16d5842cbe6b69b59bdf6fc5e5f1afcd1f0b0","analyzedAt":"2026-08-18T15:26:39.429Z","contentChangedAt":"2026-08-18T15:26:39.429Z","schemaVersion":2},"datasetVersion":"2026-09-14T00:17:10.932Z"}