RocketChat/Rocket.Chat · warning · Meteor.Error

error-transcript-already-requested

error-transcript-already-requested

Error message

error-transcript-already-requested

What it means

requestTranscript stores a pending request in room.transcriptRequest and only allows one at a time: if the field is already set (a previous transcript request has not been fulfilled/cleared yet) it throws Meteor.Error('error-transcript-already-requested', 'Transcript already requested'). The field is cleared when the transcript email is sent when the room closes.

Source

Thrown at apps/meteor/server/lib/omnichannel/sendTranscript.ts:240

	rid,
	email,
	subject,
	user,
}: {
	rid: string;
	email: string;
	subject: string;
	user: AtLeast<IUser, '_id' | 'username' | 'utcOffset' | 'name'>;
}) {
	// `v` is required by the MAC-limit check below
	const room = await LivechatRooms.findOneById(rid, { projection: { _id: 1, open: 1, transcriptRequest: 1, v: 1 } });

	if (!room?.open) {
		throw new Meteor.Error('error-invalid-room', 'Invalid room');
	}

	if (room.transcriptRequest) {
		throw new Meteor.Error('error-transcript-already-requested', 'Transcript already requested');
	}

	if (!(await Omnichannel.isWithinMACLimit(room))) {
		throw new Error('error-mac-limit-reached');
	}

	const { _id, username, name, utcOffset } = user;
	const transcriptRequest = {
		requestedAt: new Date(),
		requestedBy: {
			_id,
			username,
			name,
			utcOffset,
		},
		email,
		subject,
	};

View on GitHub (pinned to 2a7de45707)

Solutions

  1. Treat this code as an expected idempotency signal in the UI: show 'transcript already requested' instead of an error
  2. If the pending request is stale (room never closed, transcript never sent), inspect room.transcriptRequest and clear it after confirming nothing will send
  3. Debounce/disable the request button after the first successful call
  4. For API callers, check room.transcriptRequest before POSTing

Example fix

// before
await requestTranscript({ rid, email, subject, user }); // second call throws

// after
const room = await LivechatRooms.findOneById(rid, { projection: { open: 1, transcriptRequest: 1 } });
if (room?.open && !room.transcriptRequest) {
  await requestTranscript({ rid, email, subject, user });
}
Defensive patterns

Strategy: validation

Validate before calling

import { LivechatRooms } from '@rocket.chat/models';

const room = await LivechatRooms.findOneById(rid, { projection: { open: 1, transcriptRequest: 1 } });
if (room?.transcriptRequest) {
  return { alreadyRequested: true, pending: room.transcriptRequest }; // idempotent success
}
await requestTranscript({ rid, email, subject, user });

Try / catch

try {
  await requestTranscript({ rid, email, subject, user });
} catch (err) {
  if (err instanceof Meteor.Error && err.error === 'error-transcript-already-requested') {
    // treat as success-for-the-first-request: inform user a transcript is already queued
  } else {
    throw err;
  }
}

Prevention

When it happens

Trigger: Calling requestTranscript twice for the same room before the first request is processed — double-click on the button, two agents requesting a transcript for the same ongoing conversation, or a client retry that ignores the first success.

Common situations: Double-submit from the UI, aggressive API retries without idempotency, or the pending request never clearing because the closing/transcript send flow failed.

Related errors


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