RocketChat/Rocket.Chat · error · Error

error-not-allowed

error-not-allowed

Error message

error-not-allowed

What it means

Even with the request-pdf-transcript permission, the caller must pass canAccessRoomAsync(room, user) for the freshly loaded room; otherwise error-not-allowed. Feature permission and per-room access are checked separately: the first gates the route, the second gates this specific conversation.

Source

Thrown at apps/meteor/ee/server/api/v1/omnichannel/transcript.ts:24

import { requestPdfTranscript } from '../../../lib/omnichannel/requestPdfTranscript';

API.v1.addRoute(
	'omnichannel/:rid/request-transcript',
	{ authRequired: true, permissionsRequired: ['request-pdf-transcript'], license: ['livechat-enterprise'] },
	{
		async post() {
			const room = await LivechatRooms.findOneById<Pick<IOmnichannelRoom, '_id' | 'open' | 'v' | 't' | 'pdfTranscriptFileId'>>(
				this.urlParams.rid,
				{
					projection: { _id: 1, open: 1, v: 1, t: 1, pdfTranscriptFileId: 1 },
				},
			);
			if (!room) {
				throw new Error('error-invalid-room');
			}

			if (!(await canAccessRoomAsync(room, { _id: this.userId }))) {
				throw new Error('error-not-allowed');
			}

			// Flow is as follows:
			// 1. On Test Mode, call Transcript.workOnPdf directly
			// 2. On Normal Mode, call QueueWorker.queueWork to queue the work
			// 3. OmnichannelTranscript.workOnPdf will be called by the worker to generate the transcript
			// 4. We be happy :)
			await requestPdfTranscript(room, this.userId);

			return API.v1.success();
		},
	},
);

View on GitHub (pinned to b2c16d5842)

Solutions

  1. Make the request as a user who can access the room (e.g. the serving agent or a manager whose access covers that conversation).
  2. Extend the caller's roles so canAccessRoom passes for that omnichannel room (manager role, department membership, or the access rights your workspace uses).
  3. Sanity-check with rooms.info as the same user — if they cannot read the room, the transcript call will fail too.
Defensive patterns

Strategy: try-catch

Try / catch

try {
  await api.post(`/v1/omnichannel/${encodeURIComponent(rid)}/request-transcript`);
} catch (e) {
  if (e?.response?.data?.errorType === 'error-not-allowed') {
    // the caller cannot access this room: retry as the serving agent
    // or extend the user's roles so canAccessRoom passes
  } else throw e;
}

Prevention

When it happens

Trigger: An admin holding request-pdf-transcript who cannot access the target conversation (not the serving agent, not a member, and no omnichannel access rights that satisfy canAccessRoom for that room) calls POST /api/v1/omnichannel/<rid>/request-transcript.

Common situations: Back-office roles granted the transcript permission without livechat room access; requesting transcripts for other departments' conversations; service accounts with minimal roles.

Understand the failure class

Background: Permission denied / not authorized / 403 Forbidden: access-control rejections when the caller lacks the required role, grant, or ownership — this error's family across 18 libraries.

Related errors


AI-assisted analysis of RocketChat/Rocket.Chat@b2c16d5842 (2026-08-18). Data as JSON: /api/errors/b870190bbbe67724. Report an issue: GitHub.