{"record":{"id":"1529fec449516664","repo":"RocketChat/Rocket.Chat","slug":"error-not-authorized-1529fe","errorCode":null,"errorMessage":"error-not-authorized","messagePattern":"error-not-authorized","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"apps/meteor/server/api/v1/omnichannel/lib/inquiries.ts","lineNumber":28,"sourceCode":"const agentDepartments = async (userId: IUser['_id']): Promise<string[]> => {\n\tconst agentDepartments = (await LivechatDepartmentAgents.findByAgentId(userId, { projection: { departmentId: 1 } }).toArray()).map(\n\t\t({ departmentId }) => departmentId,\n\t);\n\treturn (await LivechatDepartment.findEnabledInIds(agentDepartments, { projection: { _id: 1 } }).toArray()).map(({ _id }) => _id);\n};\n\nconst applyDepartmentRestrictions = async (\n\tuserId: IUser['_id'],\n\tfilterDepartment?: string,\n): Promise<{ $in: string[] } | { $exists: false } | string> => {\n\tconst allowedDepartments = await agentDepartments(userId);\n\tif (allowedDepartments && Array.isArray(allowedDepartments) && allowedDepartments.length > 0) {\n\t\tif (!filterDepartment) {\n\t\t\treturn { $in: allowedDepartments };\n\t\t}\n\n\t\tif (!allowedDepartments.includes(filterDepartment)) {\n\t\t\tthrow new Error('error-not-authorized');\n\t\t}\n\t\treturn filterDepartment;\n\t}\n\n\treturn { $exists: false };\n};\n\nexport async function findInquiries({\n\tuserId,\n\tdepartment: filterDepartment,\n\tstatus,\n\tpagination: { offset, count, sort },\n}: {\n\tuserId: IUser['_id'];\n\tdepartment?: string;\n\tstatus?: LivechatInquiryStatus;\n\tpagination: { offset: number; count: number; sort: Record<string, number> };\n}): Promise<PaginatedResult<{ inquiries: Array<ILivechatInquiryRecord> }>> {","sourceCodeStart":10,"sourceCodeEnd":46,"githubUrl":"https://github.com/RocketChat/Rocket.Chat/blob/f9d3ec372bb580fa8d036f94cf03925a478ef768/apps/meteor/server/api/v1/omnichannel/lib/inquiries.ts#L10-L46","documentation":"Thrown inside applyDepartmentRestrictions (inquiries.ts:27-29) when an agent is department-restricted (they have one or more department assignments) and the requested `department` filter is not among their allowed departments. The allowed list is built from LivechatDepartmentAgents (by agentId) filtered through LivechatDepartment.findEnabledInIds. Returns HTTP 400 { success:false, error:'error-not-authorized' }.","triggerScenarios":"Calling findInquiries (e.g. GET /livechat/inquiries) with a `department` query param naming a department the agent is not a member of, while the agent has at least one other department assignment.","commonSituations":"Agent scoped to Department A queries Department B's queue; department membership changed but the client keeps a cached department id; multi-tenant isolation enforced via department agents.","solutions":["Omit the `department` filter so the server auto-scopes to the agent's own departments (the code returns { $in: allowedDepartments }).","Request a department the agent actually belongs to.","Grant the agent membership in the requested department (insert into LivechatDepartmentAgents) if cross-department visibility is intended."],"exampleFix":"// before\nfindInquiries({ userId, department: 'deptB-not-mine', ... }); // throws error-not-authorized\n\n// after\nfindInquiries({ userId, /* department omitted */ ... }); // auto-scoped to agent's departments","handlingStrategy":"validation","validationCode":"const allowed = (await LivechatDepartmentAgents.findByAgentId(userId, { projection: { departmentId: 1 } }).toArray())\n  .map((d) => d.departmentId);\nif (filterDepartment && !allowed.includes(filterDepartment)) {\n  // drop the filter (auto-scope) or pick an allowed department\n  filterDepartment = undefined;\n}","typeGuard":"const isAgentDepartment = async (userId: string, deptId: string) => {\n  const set = new Set((await LivechatDepartmentAgents.findByAgentId(userId, { projection: { departmentId: 1 } }).toArray()).map((d) => d.departmentId));\n  return set.has(deptId);\n};","tryCatchPattern":"try {\n  await findInquiries({ userId, department: filterDepartment, ... });\n} catch (e) {\n  if (e instanceof Error && e.message === 'error-not-authorized') {\n    // retry without the department filter to auto-scope to allowed departments\n    await findInquiries({ userId, /* no department */ ... });\n  } else { throw e; }\n}","preventionTips":["When unsure, omit the department filter so the server scopes to the agent's own departments.","Keep the client's department picker limited to departments the agent belongs to.","Refresh department membership when roles change."],"tags":["livechat","omnichannel","permission","departments","inquiries"],"backgroundTag":null,"analyzedSha":"f9d3ec372bb580fa8d036f94cf03925a478ef768","analyzedAt":"2026-08-12T19:07:17.372Z","schemaVersion":2},"datasetVersion":"2026-08-12T23:17:12.415Z"}