{"record":{"id":"0ed87b989c030ef1","repo":"RocketChat/Rocket.Chat","slug":"error-not-authorized-0ed87b","errorCode":null,"errorMessage":"error-not-authorized","messagePattern":"error-not-authorized","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"apps/meteor/ee/server/lib/omnichannel/business-hour/lib/business-hour.ts","lineNumber":14,"sourceCode":"import type { ILivechatBusinessHour } from '@rocket.chat/core-typings';\nimport { LivechatBusinessHours, LivechatDepartment } from '@rocket.chat/models';\nimport { escapeRegExp } from '@rocket.chat/string-helpers';\n\nimport { hasPermissionAsync } from '../../../../../../server/lib/authorization/hasPermission';\nimport type { IPaginatedResponse, IPagination } from '../../../../api/v1/omnichannel/lib/definition';\n\ninterface IResponse extends IPaginatedResponse {\n\tbusinessHours: ILivechatBusinessHour[];\n}\n\nexport async function findBusinessHours(userId: string, { offset, count, sort }: IPagination, name?: string): Promise<IResponse> {\n\tif (!(await hasPermissionAsync(userId, 'view-livechat-business-hours'))) {\n\t\tthrow new Error('error-not-authorized');\n\t}\n\tconst query = {};\n\tif (name) {\n\t\tconst filterReg = new RegExp(escapeRegExp(name), 'i');\n\t\tObject.assign(query, { name: filterReg });\n\t}\n\tconst { cursor, totalCount } = LivechatBusinessHours.findPaginated(query, {\n\t\tsort: sort || { name: 1 },\n\t\tskip: offset,\n\t\tlimit: count,\n\t});\n\n\tconst [businessHours, total] = await Promise.all([cursor.toArray(), totalCount]);\n\n\t// add departments to businessHours\n\tconst businessHoursWithDepartments = await Promise.all(\n\t\tbusinessHours.map(async (businessHour) => {\n\t\t\tconst currentDepartments = await LivechatDepartment.findByBusinessHourId(businessHour._id, {","sourceCodeStart":1,"sourceCodeEnd":32,"githubUrl":"https://github.com/RocketChat/Rocket.Chat/blob/f9d3ec372bb580fa8d036f94cf03925a478ef768/apps/meteor/ee/server/lib/omnichannel/business-hour/lib/business-hour.ts#L1-L32","documentation":"Thrown by findBusinessHours in business-hour.ts:14 when the caller lacks the 'view-livechat-business-hours' permission (checked via hasPermissionAsync). This is the omnichannel business-hour list/retrieval helper used by REST handlers. NOTE: plain `new Error('error-not-authorized')` — the canonical Rocket.Chat authorization code is in the message, not as a Meteor error code.","triggerScenarios":"Any REST/route that delegates to findBusinessHours being invoked by a user without 'view-livechat-business-hours': a non-agent, an omnichannel manager without the view permission, or an unauthenticated/bot token lacking the role.","commonSituations":"Custom integration token missing the livechat-manager or admin role; new role created without inheriting view-livechat-business-hours; permission revoked by an admin.","solutions":["Grant the calling user/role the 'view-livechat-business-hours' permission.","Verify the authenticated userId before invoking the helper and return 403 explicitly.","Match error by message 'error-not-authorized' (no structured code)."],"exampleFix":"// before\nconst res = await findBusinessHours(userId, pagination, name);\n\n// after\nif (!(await hasPermissionAsync(userId, 'view-livechat-business-hours'))) {\n  return res.status(403).send({ error: 'not-authorized' });\n}\nconst res = await findBusinessHours(userId, pagination, name);","handlingStrategy":"validation","validationCode":"if (!(await hasPermissionAsync(userId, 'view-livechat-business-hours'))) {\n  return res.status(403).send({ error: 'not-authorized' });\n}","typeGuard":"const canViewBH = (userId: string) => hasPermissionAsync(userId, 'view-livechat-business-hours');","tryCatchPattern":"try { await findBusinessHours(userId, pagination, name); }\ncatch (e) {\n  if (e instanceof Error && e.message === 'error-not-authorized') return res.status(403).send({ error: 'not-authorized' });\n  throw e;\n}","preventionTips":["Grant 'view-livechat-business-hours' to integration tokens/users.","Gate the route with a permission check before calling the helper."],"tags":["omnichannel","business-hour","authorization","permissions","plain-error"],"backgroundTag":null,"analyzedSha":"f9d3ec372bb580fa8d036f94cf03925a478ef768","analyzedAt":"2026-08-12T19:07:17.372Z","schemaVersion":2},"datasetVersion":"2026-08-12T23:17:12.415Z"}