RocketChat/Rocket.Chat · warning · Error
error-transcript-not-requested
error-transcript-not-requested
Error message
error-transcript-not-requested
What it means
Thrown by DELETE livechat/transcript/:rid when the room is open but room.transcriptRequest is unset. The endpoint's purpose is to cancel a pending email transcript; if none was ever requested there is nothing to cancel, so the guard rejects the call before the MAC check and the unset operation.
Source
Thrown at apps/meteor/server/api/v1/omnichannel/transcript.ts:45
{
authRequired: true,
permissionsRequired: ['send-omnichannel-chat-transcript'],
validateParams: {
POST: isPOSTLivechatTranscriptRequestParams,
},
},
{
async delete() {
const { rid } = this.urlParams;
const room = await LivechatRooms.findOneById<Pick<IOmnichannelRoom, 'open' | 'transcriptRequest' | 'v'>>(rid, {
projection: { open: 1, transcriptRequest: 1, v: 1 },
});
if (!room?.open) {
throw new Error('error-invalid-room');
}
if (!room.transcriptRequest) {
throw new Error('error-transcript-not-requested');
}
if (!(await Omnichannel.isWithinMACLimit(room))) {
throw new Error('error-mac-limit-reached');
}
await LivechatRooms.unsetEmailTranscriptRequestedByRoomId(rid);
return API.v1.success();
},
async post() {
const { rid } = this.urlParams;
const { email, subject } = this.bodyParams;
const user = await Users.findOneById(this.userId, {
projection: { _id: 1, username: 1, name: 1, utcOffset: 1 },
});
View on GitHub (pinned to f9d3ec372b)
Solutions
- Track transcript-requested state in the client and only show 'cancel' when transcriptRequest is set.
- Treat this error as a no-op success in the UI (idempotent cancel) rather than an error.
- Refresh room.transcriptRequest before rendering the cancel control.
- Guard against double-submit by disabling the button after the first click.
Example fix
// before
await DELETE('/api/v1/livechat/transcript/' + rid);
// after
if (!room.transcriptRequest) { setTranscriptRequested(false); return; }
await DELETE('/api/v1/livechat/transcript/' + rid);
setTranscriptRequested(false); Defensive patterns
Strategy: validation
Validate before calling
const room = await LivechatRooms.findOneById(rid, { projection: { open: 1, transcriptRequest: 1 } });
if (room?.open && !room.transcriptRequest) { setTranscriptRequested(false); return; /* nothing to cancel */ } Type guard
const hasPendingTranscript = (r: { transcriptRequest?: unknown } | null): boolean => !!r?.transcriptRequest; Try / catch
try {
await DELETE('/api/v1/livechat/transcript/' + rid);
} catch (e) {
if (e.message === 'error-transcript-not-requested') { setTranscriptRequested(false); return; /* idempotent */ }
throw e;
} Prevention
- Track transcript-requested state in the client; only show cancel when set.
- Make cancel idempotent in the UI (second click is a no-op).
- Refresh room.transcriptRequest before rendering the cancel control.
When it happens
Trigger: DELETE /api/v1/livechat/transcript/<rid> on an open room where POST livechat/transcript/:rid (requestTranscript) was never called, or where the transcriptRequest field was already cleared (e.g. by a prior successful delete, or by the transcript being sent).
Common situations: User double-clicks cancel (second call hits this); UI shows a cancel button based on stale state; transcript was already sent/cleared by the system; client lost track of whether it requested a transcript.
Related errors
- error-invalid-room
- error-invalid-sla
- error-forwarding-department-target-not-allowed
- error-invalid-sla
- error-invalid-priority
AI-assisted analysis of RocketChat/Rocket.Chat@f9d3ec372b (2026-08-12).
Data as JSON: /api/errors/92d4779e8eb3ddf2.
Report an issue: GitHub.