{"record":{"id":"826742716d8d3e5f","repo":"RocketChat/Rocket.Chat","slug":"room-closed","errorCode":null,"errorMessage":"room-closed","messagePattern":"room-closed","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"apps/meteor/server/api/v1/omnichannel/message.ts","lineNumber":42,"sourceCode":"API.v1.addRoute(\n\t'livechat/message',\n\t{ validateParams: isPOSTLivechatMessageParams },\n\t{\n\t\tasync post() {\n\t\t\tconst { token, rid, agent, msg } = this.bodyParams;\n\n\t\t\tconst guest = await findGuest(token);\n\t\t\tif (!guest) {\n\t\t\t\tthrow new Error('invalid-token');\n\t\t\t}\n\n\t\t\tconst room = await findRoom(token, rid);\n\t\t\tif (!room) {\n\t\t\t\tthrow new Error('invalid-room');\n\t\t\t}\n\n\t\t\tif (!room.open) {\n\t\t\t\tthrow new Error('room-closed');\n\t\t\t}\n\n\t\t\tif (\n\t\t\t\tsettings.get('Livechat_enable_message_character_limit') &&\n\t\t\t\tmsg.length > parseInt(settings.get('Livechat_message_character_limit'))\n\t\t\t) {\n\t\t\t\tthrow new Error('message-length-exceeds-character-limit');\n\t\t\t}\n\n\t\t\tconst _id = this.bodyParams._id || Random.id();\n\n\t\t\tconst messageToSend = {\n\t\t\t\tguest,\n\t\t\t\tmessage: {\n\t\t\t\t\t_id,\n\t\t\t\t\trid,\n\t\t\t\t\tmsg,\n\t\t\t\t\ttoken,","sourceCodeStart":24,"sourceCodeEnd":60,"githubUrl":"https://github.com/RocketChat/Rocket.Chat/blob/f9d3ec372bb580fa8d036f94cf03925a478ef768/apps/meteor/server/api/v1/omnichannel/message.ts#L24-L60","documentation":"Thrown by POST /livechat/message (message.ts:41-43) when the room exists and belongs to the visitor but room.open is false — the livechat conversation has been closed (by agent, visitor, inactivity auto-close, etc.). Returns HTTP 400 { success:false, error:'room-closed' }.","triggerScenarios":"Sending a message to a livechat room whose `open` flag is false.","commonSituations":"Chat ended by agent or visitor; auto-close after inactivity timeout; attempting to reply after the session was closed.","solutions":["Start a new livechat session / reopen the chat to obtain a new open room before sending.","Inspect room.open before posting; if closed, prompt the user to begin a new conversation.","If reopening is supported in your flow, re-open the existing room and retry."],"exampleFix":"// before\nPOST /livechat/message { token, rid, msg } // room-closed\n\n// after\nconst room = await findRoom(token, rid);\nif (room && !room.open) { /* start new conversation / reopen chat */ }\nPOST /livechat/message { token, rid, msg }","handlingStrategy":"validation","validationCode":"const room = await findRoom(token, rid);\nif (room && !room.open) {\n  // start a new conversation / reopen, then retry\n  throw new Error('room is closed');\n}\n// safe to POST /livechat/message","typeGuard":"const isRoomOpen = (room: IOmnichannelRoom | null): room is IOmnichannelRoom =>\n  !!room && room.open === true;","tryCatchPattern":"try { await sendMessage({ token, rid, msg }); }\ncatch (e) { if (e instanceof Error && e.message === 'room-closed') { /* prompt new conversation */ } else throw e; }","preventionTips":["Check room.open before sending.","Treat closed chats as terminal; start a new session instead of hammering retries.","Surface 'conversation ended' UI on room-closed."],"tags":["livechat","omnichannel","room","messaging","rest-api"],"backgroundTag":null,"analyzedSha":"f9d3ec372bb580fa8d036f94cf03925a478ef768","analyzedAt":"2026-08-12T19:07:17.372Z","schemaVersion":2},"datasetVersion":"2026-08-12T23:17:12.415Z"}