{"record":{"id":"d3e018a064f58d05","repo":"RocketChat/Rocket.Chat","slug":"error-room-onhold","errorCode":"error-room-onHold","errorMessage":"error-room-onHold","messagePattern":"error-room-onHold","errorType":"exception","errorClass":"Meteor.Error","httpStatus":null,"severity":"error","filePath":"apps/meteor/server/lib/omnichannel/rooms.ts","lineNumber":227,"sourceCode":"\n\t\tif (responses[2]?.modifiedCount) {\n\t\t\tawait notifyOnSubscriptionChangedByRoomId(rid);\n\t\t}\n\t}\n\n\tvoid notifyOnRoomChangedById(roomData._id);\n\n\treturn true;\n}\n\nexport async function returnRoomAsInquiry(room: IOmnichannelRoom, departmentId?: string, overrideTransferData: Partial<TransferData> = {}) {\n\tlivechatLogger.debug({ msg: 'Transferring room to queue', scope: departmentId ? 'department' : undefined, room });\n\tif (!room.open) {\n\t\tthrow new Meteor.Error('room-closed', 'Room closed');\n\t}\n\n\tif (room.onHold) {\n\t\tthrow new Meteor.Error('error-room-onHold');\n\t}\n\n\tif (!(await Omnichannel.isWithinMACLimit(room))) {\n\t\tthrow new Meteor.Error('error-mac-limit-reached');\n\t}\n\n\tif (!room.servedBy) {\n\t\treturn false;\n\t}\n\n\tconst user = await Users.findOneById(room.servedBy._id);\n\tif (!user?._id) {\n\t\tthrow new Meteor.Error('error-invalid-user');\n\t}\n\n\tconst inquiry = await LivechatInquiry.findOne({ rid: room._id });\n\tif (!inquiry) {\n\t\treturn false;","sourceCodeStart":209,"sourceCodeEnd":245,"githubUrl":"https://github.com/RocketChat/Rocket.Chat/blob/b2c16d5842cbe6b69b59bdf6fc5e5f1afcd1f0b0/apps/meteor/server/lib/omnichannel/rooms.ts#L209-L245","documentation":"Second guard in returnRoomAsInquiry: rooms flagged onHold cannot be returned to the queue and raise Meteor.Error('error-room-onHold'). An on-hold room must leave the hold state before it can re-enter the queue.","triggerScenarios":"Returning a room to the queue while it is on hold — the visitor stopped responding and the on-hold conversations feature flagged the room.","commonSituations":"On-hold chats still visible in transfer lists; bulk-transfer automation that does not filter onHold rooms; agents unaware a room was auto-placed on hold.","solutions":["Take the room off hold (resume the on-hold conversation) before transferring it to the queue.","Filter onHold rooms out of bulk transfer/return jobs.","Check the room's On-Hold conversations state (Administration > Omnichannel) to understand why it was held."],"exampleFix":"// before\nawait returnRoomAsInquiry(room, departmentId); // throws error-room-onHold\n\n// after\nif (room.onHold) {\n\tthrow new Error('resume the on-hold conversation before transferring');\n}\nawait returnRoomAsInquiry(room, departmentId);","handlingStrategy":"validation","validationCode":"if (room.onHold) {\n\tthrow new Error('resume the on-hold conversation before returning it to the queue');\n}\nawait returnRoomAsInquiry(room, departmentId);","typeGuard":"const isReturnableToQueue = (room: Pick<IOmnichannelRoom, 'open' | 'onHold'>): boolean =>\n\troom.open === true && room.onHold !== true;","tryCatchPattern":"try {\n\tawait returnRoomAsInquiry(room, departmentId);\n} catch (err) {\n\tif (err instanceof Meteor.Error && err.error === 'error-room-onHold') {\n\t\t// prompt the agent to resume the on-hold room first\n\t\treturn;\n\t}\n\tthrow err;\n}","preventionTips":["Show on-hold status in transfer lists so agents filter those rooms.","Bulk automation must skip rooms with onHold set.","Understand the on-hold lifecycle (auto on-hold after inactivity) before building transfer tooling."],"tags":["omnichannel","livechat","rooms","on-hold","invalid-state"],"backgroundTag":"invalid-room-state","analyzedSha":"b2c16d5842cbe6b69b59bdf6fc5e5f1afcd1f0b0","analyzedAt":"2026-08-18T15:26:39.429Z","schemaVersion":2},"datasetVersion":"2026-08-21T18:17:14.833Z"}