RocketChat/Rocket.Chat · error · Error
error-not-authorized
Error message
error-not-authorized
What it means
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.
Source
Thrown at apps/meteor/ee/server/lib/omnichannel/business-hour/lib/business-hour.ts:14
import type { ILivechatBusinessHour } from '@rocket.chat/core-typings';
import { LivechatBusinessHours, LivechatDepartment } from '@rocket.chat/models';
import { escapeRegExp } from '@rocket.chat/string-helpers';
import { hasPermissionAsync } from '../../../../../../server/lib/authorization/hasPermission';
import type { IPaginatedResponse, IPagination } from '../../../../api/v1/omnichannel/lib/definition';
interface IResponse extends IPaginatedResponse {
businessHours: ILivechatBusinessHour[];
}
export async function findBusinessHours(userId: string, { offset, count, sort }: IPagination, name?: string): Promise<IResponse> {
if (!(await hasPermissionAsync(userId, 'view-livechat-business-hours'))) {
throw new Error('error-not-authorized');
}
const query = {};
if (name) {
const filterReg = new RegExp(escapeRegExp(name), 'i');
Object.assign(query, { name: filterReg });
}
const { cursor, totalCount } = LivechatBusinessHours.findPaginated(query, {
sort: sort || { name: 1 },
skip: offset,
limit: count,
});
const [businessHours, total] = await Promise.all([cursor.toArray(), totalCount]);
// add departments to businessHours
const businessHoursWithDepartments = await Promise.all(
businessHours.map(async (businessHour) => {
const currentDepartments = await LivechatDepartment.findByBusinessHourId(businessHour._id, {View on GitHub (pinned to f9d3ec372b)
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).
Example fix
// before
const res = await findBusinessHours(userId, pagination, name);
// after
if (!(await hasPermissionAsync(userId, 'view-livechat-business-hours'))) {
return res.status(403).send({ error: 'not-authorized' });
}
const res = await findBusinessHours(userId, pagination, name); Defensive patterns
Strategy: validation
Validate before calling
if (!(await hasPermissionAsync(userId, 'view-livechat-business-hours'))) {
return res.status(403).send({ error: 'not-authorized' });
} Type guard
const canViewBH = (userId: string) => hasPermissionAsync(userId, 'view-livechat-business-hours');
Try / catch
try { await findBusinessHours(userId, pagination, name); }
catch (e) {
if (e instanceof Error && e.message === 'error-not-authorized') return res.status(403).send({ error: 'not-authorized' });
throw e;
} Prevention
- Grant 'view-livechat-business-hours' to integration tokens/users.
- Gate the route with a permission check before calling the helper.
When it happens
Trigger: 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.
Common situations: Custom integration token missing the livechat-manager or admin role; new role created without inheriting view-livechat-business-hours; permission revoked by an admin.
Related errors
- error-business-hour-name-already-in-use
- error-not-allowed
- error-not-authorized
- unit-not-found
- error-unit-not-found
AI-assisted analysis of RocketChat/Rocket.Chat@f9d3ec372b (2026-08-12).
Data as JSON: /api/errors/0ed87b989c030ef1.
Report an issue: GitHub.