RocketChat/Rocket.Chat · error · Error
error-invalid-room
Error message
error-invalid-room
What it means
Thrown by POST /api/v1/livechat/room.forward when LivechatRooms.findOneById(roomId) returns null OR the found room's type is not 'l'. Both 'no such room' and 'room exists but is not an omnichannel room' collapse into this single error before any transfer logic runs.
Solutions
- Confirm the rid refers to an omnichannel room (e.g. GET livechat/rooms, or check room.t === 'l' in whatever source produced it)
- Re-fetch the room list and use a current _id
- Check server logs for the exact roomId received to spot truncation/encoding issues
Example fix
// before
forward({ roomId: channel._id, ... }); // channel rid, t !== 'l'
// after
if (room.t !== 'l') throw new Error('cannot forward a non-omnichannel room');
forward({ roomId: room._id, ... }); Defensive patterns
Strategy: type-guard
Validate before calling
const rooms = await (await fetch(`${url}/api/v1/livechat/rooms`, { headers: authHeaders })).json();
const target = rooms.rooms?.find((r) => r._id === roomId && r.t === 'l');
if (!target) throw new Error('cannot forward: not an omnichannel room'); Type guard
function isLivechatRoomId(room) {
return Boolean(room) && room.t === 'l' && typeof room._id === 'string';
} Try / catch
try { await forward(roomId, payload); } catch (e) { if (e.message === 'error-invalid-room') { await refreshRoomCache(); return; } throw e; } Prevention
- Source rids only from omnichannel room listings (t === 'l')
- Re-validate cached rids before forwarding
- Never forward ids taken from channel/DM payloads
When it happens
Trigger: Authenticated call (requires view-l-room + transfer-livechat-guest permissions) with a roomId that does not exist, a roomId of a regular channel/group/DM, or a truncated/malformed ObjectId.
Common situations: Integration forwards a rid taken from a normal chat payload instead of an omnichannel room; room deleted between listing and forwarding; copy/paste truncation of the _id.
Understand the failure class
Background: 'Could not be found', 'does not exist', 'not found in database': the resource-not-found family when an ID, slug, key, or URI lookup comes back empty — this error's family across 20 libraries.
Related errors
- error-forwarding-chat
- error-invalid-visitor
- invalid-room
- agent-not-found
- error-forwarding-chat-same-department
AI-assisted analysis of RocketChat/Rocket.Chat@b2c16d5842 (2026-08-18).
Data as JSON: /api/errors/9b3ee251ec18bd35.
Report an issue: GitHub.
Appendix: source
Thrown at apps/meteor/server/api/v1/omnichannel/room.ts:296
return API.v1.success({ rid, data: updateData });
},
},
);
API.v1.addRoute(
'livechat/room.forward',
{ authRequired: true, permissionsRequired: ['view-l-room', 'transfer-livechat-guest'], validateParams: isLiveChatRoomForwardProps },
{
async post() {
const transferData = this.bodyParams as typeof this.bodyParams & {
transferredBy: TransferByData;
transferredTo?: { _id: string; username?: string; name?: string };
};
const room = await LivechatRooms.findOneById(this.bodyParams.roomId);
if (room?.t !== 'l') {
throw new Error('error-invalid-room');
}
if (!room.open) {
throw new Error('This_conversation_is_already_closed');
}
if (!(await Omnichannel.isWithinMACLimit(room))) {
throw new Error('error-mac-limit-reached');
}
const guest = await LivechatVisitors.findOneEnabledById(room.v?._id);
if (!guest) {
throw new Error('error-invalid-visitor');
}
transferData.transferredBy = normalizeTransferredByData(this.user, room);
if (transferData.userId) {
const userToTransfer = await Users.findOneById(transferData.userId);View on GitHub (pinned to b2c16d5842)