{"record":{"id":"a81eed22104211ae","repo":"RocketChat/Rocket.Chat","slug":"invalid-room-a81eed","errorCode":null,"errorMessage":"invalid-room","messagePattern":"invalid-room","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"apps/meteor/server/api/v1/omnichannel/visitors.ts","lineNumber":172,"sourceCode":"\t\t\t\t}),\n\t\t\t);\n\t\t},\n\t},\n);\n\nAPI.v1.addRoute(\n\t'livechat/:rid/messages',\n\t{ authRequired: true, permissionsRequired: ['view-l-room'], validateParams: isLivechatRidMessagesProps },\n\t{\n\t\tasync get() {\n\t\t\tconst { offset, count } = await getPaginationItems(this.queryParams);\n\t\t\tconst { sort } = await this.parseJsonQuery();\n\t\t\tconst { searchTerm } = this.queryParams;\n\n\t\t\tconst room = await LivechatRooms.findOneById(this.urlParams.rid);\n\n\t\t\tif (!room) {\n\t\t\t\tthrow new Error('invalid-room');\n\t\t\t}\n\n\t\t\tif (!(await canAccessRoomAsync(room, this.user))) {\n\t\t\t\tthrow new Error('not-allowed');\n\t\t\t}\n\n\t\t\tconst { cursor, totalCount } = Messages.findLivechatClosedMessages(this.urlParams.rid, searchTerm, {\n\t\t\t\tsort: sort || { ts: -1 },\n\t\t\t\tskip: offset,\n\t\t\t\tlimit: count,\n\t\t\t});\n\n\t\t\tconst [messages, total] = await Promise.all([cursor.toArray(), totalCount]);\n\n\t\t\treturn API.v1.success({\n\t\t\t\tmessages: await normalizeMessagesForUser(messages, this.userId),\n\t\t\t\toffset,\n\t\t\t\tcount,","sourceCodeStart":154,"sourceCodeEnd":190,"githubUrl":"https://github.com/RocketChat/Rocket.Chat/blob/f9d3ec372bb580fa8d036f94cf03925a478ef768/apps/meteor/server/api/v1/omnichannel/visitors.ts#L154-L190","documentation":"Thrown by GET livechat/:rid/messages when LivechatRooms.findOneById(this.urlParams.rid) returns null. The route requires view-l-room permission and validates params via isLivechatRidMessagesProps, but existence of the room is checked here by id lookup.","triggerScenarios":"GET /api/v1/v1/livechat/<rid>/messages with a rid absent from the rooms collection; rid from a deleted/closed-and-pruned conversation; message id mistakenly used in place of rid.","commonSituations":"Frontend cached a rid past its lifetime; URL parameter mis-substitution; integration paginating over a rid list that included a stale entry.","solutions":["Re-resolve the rid from the current livechat rooms before fetching messages.","Filter out stale rids client-side before issuing the request.","Treat invalid-room on this endpoint as a signal to refresh the room list."],"exampleFix":"null","handlingStrategy":"validation","validationCode":"if (!/^[A-Za-z0-9]{17}$/.test(rid)) throw new Error('bad rid');\nconst room = await fetch(`/api/v1/v1/livechat/${rid}/messages`);","typeGuard":"null","tryCatchPattern":"try { await fetch(url); } catch (e) { if (e.error === 'invalid-room') { /* refresh room list, drop stale rid */ } }","preventionTips":["Resolve rid from a current rooms listing.","Drop stale rids from pagination cursors.","Validate rid format client-side."],"tags":["omnichannel","messages","room","not-found"],"backgroundTag":null,"analyzedSha":"f9d3ec372bb580fa8d036f94cf03925a478ef768","analyzedAt":"2026-08-12T19:07:17.372Z","schemaVersion":2},"datasetVersion":"2026-08-12T23:17:12.415Z"}