RocketChat/Rocket.Chat · critical · Error
error-invalid-inquiry
Error message
error-invalid-inquiry
What it means
Thrown by runVerifyContactChannel after the contact merge transaction succeeds but LivechatInquiry.findOneByRoomId(roomId) returns null. The comment in code marks this as 'something is really wrong with the queue' — an inquiry is expected to exist for any omnichannel room in this flow. Throwing prevents carrying on a half-verified state where the contact was merged but no inquiry exists to re-queue.
Source
Thrown at apps/meteor/ee/server/patches/verifyContactChannel.ts:88
const room = await LivechatRooms.findOneById(roomId);
if (!room) {
throw new Error('error-invalid-room');
}
const result = await _verifyContactChannel(params, room);
logger.debug({ msg: 'Finding inquiry', roomId });
// Note: we are not using the session here since allowing the transactional flow to be used inside the
// saveQueueInquiry function would require a lot of changes across the codebase, so if we fail here we
// will not be able to rollback the transaction. That is not a big deal since the contact will be properly
// merged and the inquiry will be saved in the queue (will need to be taken manually by an agent though).
const inquiry = await LivechatInquiry.findOneByRoomId(roomId);
if (!inquiry) {
// Note: if this happens, something is really wrong with the queue, so we should throw an error to avoid
// carrying on a weird state.
throw new Error('error-invalid-inquiry');
}
if (inquiry.status === LivechatInquiryStatus.VERIFYING) {
logger.debug({ msg: 'Verifying inquiry', roomId });
await QueueManager.verifyInquiry(inquiry, room);
}
logger.debug({
msg: 'Contact channel has been verified and merged successfully',
contactId,
visitorId,
roomId,
});
return result;
};
verifyContactChannel.patch(runVerifyContactChannel, () => License.hasModule('contact-id-verification'));View on GitHub (pinned to f9d3ec372b)
Solutions
- Investigate why the inquiry is missing (audit logs, manual db deletion, failed migration).
- Re-create or restore the inquiry for the room so the queue is consistent.
- If the room is stale/closed, mark the verification as moot instead of continuing.
- Add a reconciliation job that repairs rooms whose inquiry is absent.
Defensive patterns
Strategy: try-catch
Validate before calling
async function inquiryExistsForRoom(roomId: string): Promise<boolean> {
const inq = await LivechatInquiry.findOneByRoomId(roomId, { projection: { _id: 1 } });
return Boolean(inq);
} Try / catch
try {
await verifyContactChannel(params);
} catch (e) {
if (e.message === 'error-invalid-inquiry') {
// page an admin / run a queue reconciliation job
} else throw e;
} Prevention
- Run a periodic reconciliation job that repairs rooms without inquiries.
- Audit manual db deletions of inquiry documents.
- Alert operations when this fires — it signals queue corruption.
- Validate inquiry presence after any migration touching livechat_inquiry.
When it happens
Trigger: The room exists, the contact/channel merge committed, but the associated livechat inquiry document is missing — typically because it was removed, the room was never properly queued, or another worker already took and closed it.
Common situations: Queue corruption from a partial migration, manual DB deletion of inquiries, a previously failed take-inquiry that left no inquiry behind, or a room created outside the normal omnichannel queueing path.
Related errors
- error-invalid-inquiry
- error-contact-not-found
- error-action-not-allowed
- error-max-number-simultaneous-chats-reached
- SLA not found with id: ${slaId}
AI-assisted analysis of RocketChat/Rocket.Chat@f9d3ec372b (2026-08-12).
Data as JSON: /api/errors/dd153fc05efab0a8.
Report an issue: GitHub.