RocketChat/Rocket.Chat · error · Error
error-room-cannot-be-closed-try-again
error-room-cannot-be-closed-try-again
Error message
error-room-cannot-be-closed-try-again
What it means
closeRoom performs its closing writes inside a MongoDB transaction with a bounded retry loop for transient errors (shouldRetryTransaction). When the retries are exhausted on a transient error (write conflict, primary stepdown, network blip), it aborts the session and throws Error('error-room-cannot-be-closed-try-again'). The room is left open and consistent - the transaction rolled back cleanly.
Source
Thrown at apps/meteor/server/lib/omnichannel/closeRoom.ts:55
const { room, closedBy, removedInquiry } = await doCloseRoom(params, session);
await session.commitTransaction();
newRoom = room;
chatCloser = closedBy;
removedInquiryObj = removedInquiry;
} catch (e) {
logger.error({ err: e, msg: 'Failed to close room', afterAttempts: attempts });
if (session.inTransaction()) {
await session.abortTransaction();
}
// Dont propagate transaction errors
if (shouldRetryTransaction(e)) {
if (attempts > 0) {
logger.debug({ msg: 'Retrying close room because of transient error', attemptsLeft: attempts });
return closeRoom(params, attempts - 1);
}
throw new Error('error-room-cannot-be-closed-try-again');
}
throw e;
} finally {
await session.endSession();
}
// Note: when reaching this point, the room has been closed
// Transaction is commited and so these messages can be sent here.
return afterRoomClosed(newRoom, chatCloser, removedInquiryObj, params);
}
async function afterRoomClosed(
newRoom: IOmnichannelRoom,
chatCloser: ChatCloser,
inquiry: ILivechatInquiryRecord | null,
params: CloseRoomParams,
): Promise<void> {
if (!chatCloser) {View on GitHub (pinned to b2c16d5842)
Solutions
- Retry the close after a short backoff - the error message explicitly says try again
- Check MongoDB health: replica set status, primary stability, replication lag
- Stagger bulk-close batches instead of firing all closes concurrently
- If persistent, inspect logs for the underlying Mongo error (write conflicts, NoSuchTransaction) and resolve the contention source
Defensive patterns
Strategy: retry
Try / catch
const closeWithBackoff = async (params: CloseRoomParams, attempts = 4): Promise<void> => {
try {
await closeRoom(params);
} catch (err: any) {
if (err?.message === 'error-room-cannot-be-closed-try-again' && attempts > 0) {
await sleep(2 ** (4 - attempts) * 250); // 250ms, 500ms, 1s, 2s
return closeWithBackoff(params, attempts - 1);
}
throw err;
}
}; Prevention
- Run MongoDB as a healthy replica set - transactions fail noisily during failovers and stepdowns
- Stagger bulk-close operations to avoid write-conflict storms on shared room/inquiry documents
- Alert on repeated 'try-again' failures: sustained occurrence means Mongo contention or instability, not bad input
When it happens
Trigger: Heavy concurrent writes to the same room/inquiry documents (parallel closes, message bursts) repeatedly causing TransientTransactionError/UnknownTransactionCommitResult; a MongoDB replica set failover or primary stepdown mid-close; a degraded or undersized replica set under load.
Common situations: Bulk-closing many chats at once (e.g. closeOpenChats for agents with huge loads); multi-instance deployments fanning out closes; Mongo under backup/migration pressure; replica sets with lagging secondaries or frequent elections.
Related errors
- Something went wrong while trying to commit changes. Please
- error-verifying-contact-channel
- error-invalid-visitor
- error-agent-is-locked
- error-failed-to-delete-department
AI-assisted analysis of RocketChat/Rocket.Chat@b2c16d5842 (2026-08-18).
Data as JSON: /api/errors/417dc81094964d87.
Report an issue: GitHub.