RocketChat/Rocket.Chat · error · Error
error-invalid-room
error-invalid-room
Error message
error-invalid-room
What it means
Thrown by sendTranscript in apps/meteor/server/lib/omnichannel/sendTranscript.ts when LivechatRooms.findOneById(rid) returns null. Only livechat (omnichannel) rooms live in the LivechatRooms collection, so a missing document means the rid either does not exist or is not a livechat room. It is a plain Error (not Meteor.Error) with the code as its message.
Source
Thrown at apps/meteor/server/lib/omnichannel/sendTranscript.ts:49
export async function sendTranscript({
token,
rid,
email,
subject,
user,
}: {
token: string;
rid: string;
email: string;
subject?: string;
user?: Pick<IUser, '_id' | 'name' | 'username' | 'utcOffset'> | null;
}): Promise<boolean> {
logger.debug({ msg: 'Sending conversation transcript', rid, token });
const room = await LivechatRooms.findOneById<Pick<IOmnichannelRoom, '_id' | 'v'>>(rid, { projection: { _id: 1, v: 1 } });
if (!room) {
throw new Error('error-invalid-room');
}
const visitor = room?.v as ILivechatVisitor;
if (token !== visitor?.token) {
throw new Error('error-invalid-visitor');
}
const userLanguage = settings.get<string>('Language') || 'en';
const timezone = getTimezone(user);
logger.debug({ msg: 'Transcript will be sent using timezone', timezone });
const showAgentInfo = settings.get<boolean>('Livechat_show_agent_info');
const showSystemMessages = settings.get<boolean>('Livechat_transcript_show_system_messages');
const closingMessage = await Messages.findLivechatClosingMessage(rid, { projection: { ts: 1 } });
const ignoredMessageTypes: MessageTypesValues[] = [
'livechat_navigation_history',
'livechat_transcript_history',
'command',View on GitHub (pinned to b2c16d5842)
Solutions
- Log/verify the rid passed to sendTranscript and confirm it is an omnichannel room id (t: 'l')
- Check the room still exists: db.rocketchat_room.findOne({_id: rid, t: 'l'})
- If the room was deleted, the transcript cannot be produced from room data — regenerate from message history only if you keep backups
- Fix the caller (widget/integration) to pass the rid returned by the livechat room creation API
Defensive patterns
Strategy: validation
Validate before calling
import { LivechatRooms } from '@rocket.chat/models';
const room = await LivechatRooms.findOneById(rid, { projection: { _id: 1, v: 1 } });
if (!room) {
// fail early with your own error instead of error-invalid-room deep in sendTranscript
throw new Error(`no livechat room ${rid}`);
}
await sendTranscript({ rid, token, email, room }); Type guard
function isLivechatRoom(v: { t?: string } | null | undefined): v is { _id: string; t: 'l'; v: { token: string } } {
return !!v && v.t === 'l' && typeof v.v?.token === 'string';
} Try / catch
try {
await sendTranscript({ rid, token, email });
} catch (err) {
if (err instanceof Error && err.message === 'error-invalid-room') {
// room missing: surface a user-facing 'conversation not found' and stop
} else {
throw err;
}
} Prevention
- Always source the rid from the livechat room-creation/visitor APIs rather than user input
- Treat error-invalid-room as permanent — do not retry; fix the id instead
- In integrations, validate rid shape and existence before the transcript call
When it happens
Trigger: Calling sendTranscript({ rid, token, email }) with a rid that has no document in LivechatRooms: a typo'd id, a regular channel id, a room that was already deleted, or a race where the room was removed right before the call.
Common situations: Passing a channel/group id instead of the livechat room id from the widget, transcript requested after the room was purged by retention/cleanup jobs, or truncated/copied ids in integrations.
Related errors
- Invalid type
- error-invalid-room
- error-not-allowed
- error-duplicated-sla
- error-business-hour-name-already-in-use
AI-assisted analysis of RocketChat/Rocket.Chat@b2c16d5842 (2026-08-18).
Data as JSON: /api/errors/4537df5175240624.
Report an issue: GitHub.