RocketChat/Rocket.Chat · error · Error
error-transcript-not-requested
Error message
error-transcript-not-requested
What it means
Thrown by DELETE /api/v1/livechat/transcript/:rid when the room exists and is open but has no transcriptRequest field — i.e. nobody ever requested an emailed transcript for that room. The DELETE endpoint exists only to cancel a pending transcript request, so it refuses when there is nothing pending.
Solutions
- Only call DELETE after a successful POST /api/v1/livechat/transcript/:rid on the same room
- Treat a second cancellation as a no-op (catch this error and continue)
- Make your cancel operation idempotent by tracking whether a request is outstanding per rid
Defensive patterns
Strategy: validation
Validate before calling
// Track request state per rid in your client instead of relying on the server to remember
if (transcriptRequestedByRid.has(rid)) {
await cancelTranscript(rid);
transcriptRequestedByRid.delete(rid);
} Try / catch
const body = await (await fetch(`${server}/api/v1/livechat/transcript/${rid}`, { method: 'DELETE', headers })).json();
if (!body.success && body.error === 'error-transcript-not-requested') { /* idempotent: nothing pending */ } Prevention
- Make cancel idempotent: swallow error-transcript-not-requested as success
- Only expose 'cancel transcript' UI after a successful POST transcript
When it happens
Trigger: Calling DELETE on an open room before anyone called POST /api/v1/livechat/transcript/:rid; calling DELETE twice (the first call unsets transcriptRequest, so the second hits this); the visitor requested the transcript via the widget and you then cancel it twice from an integration.
Common situations: Duplicate webhooks/cron jobs firing the cancel twice; UI allowing the 'cancel transcript' button when no request was made because state was not refreshed after the first cancellation.
Understand the failure class
Background: "Invalid state transition" errors: "status must be X, actually Y", "already rejected/charging/uninstalled", "cannot ... while running" — what they mean when a library rejects your call — this error's family across 31 libraries.
Related errors
AI-assisted analysis of RocketChat/Rocket.Chat@b2c16d5842 (2026-08-18).
Data as JSON: /api/errors/92d4779e8eb3ddf2.
Report an issue: GitHub.
Appendix: 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 b2c16d5842)