RocketChat/Rocket.Chat · error · Error
invalid-room
invalid-room
Error message
invalid-room
What it means
Thrown by GET /api/v1/livechat/:rid/messages (requires auth plus the view-l-room permission) when LivechatRooms.findOneById(rid) returns null — the URL segment is not the _id of an existing livechat room. The endpoint lists a livechat room's closed/session messages, so passing a regular channel/group rid, a deleted room's rid, or a malformed id fails this lookup before any access check runs.
Solutions
- Source rids only from livechat APIs: GET /api/v1/livechat/rooms (agent view) or the visitor's own history endpoints, never channels.list
- Sanity-check the rid shape before calling — Rocket.Chat ids are 17-character alphanumeric strings
- If rooms can vanish underneath you (retention), catch this error and drop the rid from your cache instead of retrying
Example fix
// before
const { messages } = await sdk.get(`livechat/${rid}/messages`);
// after (validate rid shape, then call)
if (!/^[A-Za-z0-9]{17}$/.test(rid)) throw new Error(`malformed rid: ${rid}`);
const { messages } = await sdk.get(`livechat/${rid}/messages`); Defensive patterns
Strategy: validation
Validate before calling
const isValidRid = (rid: string) => /^[A-Za-z0-9]{17}$/.test(rid);
if (!isValidRid(rid)) throw new Error(`malformed rid: ${JSON.stringify(rid)}`);
// prefer sourcing rids from livechat data:
const { rooms } = await sdk.get('livechat/rooms', { count: 1 }); // rooms the agent can access Type guard
const isLivechatRoomId = (rid: unknown): rid is string =>
typeof rid === 'string' && /^[A-Za-z0-9]{17}$/.test(rid); Try / catch
catch error 'invalid-room' and evict the rid from your local cache/queue — the room is gone or was never a livechat room; retrying with the same id cannot succeed.
Prevention
- Only accept rids from livechat endpoints (livechat/rooms, visitor history)
- Validate the 17-char id shape before every call
- When retention deletes rooms, expect stale rids and handle removal gracefully
When it happens
Trigger: GET /api/v1/livechat/<rid>/messages where rid is a typo'd or truncated 17-char id, the _id of a normal channel or private group instead of a livechat room, or the id of a livechat room that was deleted (retention/pruning or omnichannel cleanup).
Common situations: Reusing rids captured in a different environment; copy-pasting a message id or visitor token into the rid slot; room disappeared between listing it and fetching messages; code that assumes any room id works for livechat endpoints.
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
AI-assisted analysis of RocketChat/Rocket.Chat@2a7de45707 (2026-08-18).
Data as JSON: /api/errors/a81eed22104211ae.
Report an issue: GitHub.
Appendix: source
Thrown at apps/meteor/server/api/v1/omnichannel/visitors.ts:178
}),
);
},
},
);
API.v1.addRoute(
'livechat/:rid/messages',
{ authRequired: true, permissionsRequired: ['view-l-room'], validateParams: isLivechatRidMessagesProps },
{
async get() {
const { offset, count } = await getPaginationItems(this.queryParams);
const { sort } = await this.parseJsonQuery();
const { searchTerm } = this.queryParams;
const room = await LivechatRooms.findOneById(this.urlParams.rid);
if (!room) {
throw new Error('invalid-room');
}
if (!(await canAccessRoomAsync(room, this.user))) {
throw new Error('not-allowed');
}
const { cursor, totalCount } = Messages.findLivechatClosedMessages(this.urlParams.rid, searchTerm, {
sort: sort || { ts: -1 },
skip: offset,
limit: count,
});
const [messages, total] = await Promise.all([cursor.toArray(), totalCount]);
return API.v1.success({
messages: await normalizeMessagesForUser(messages, this.userId),
offset,
count,View on GitHub (pinned to 2a7de45707)