RocketChat/Rocket.Chat · error · Meteor.Error
error-room-does-not-exist
error-room-does-not-exist
Error message
This room does not exist
What it means
Thrown by chat.readThread when Rooms.findOneById(thread.rid, ...) returns null - the room referenced by the thread parent message no longer exists in the Rooms collection. Meteor.Error code 'error-room-does-not-exist'. This is a data-integrity edge: the message exists but its room is gone.
Source
Thrown at apps/meteor/server/api/v1/chat.ts:298
async function action() {
if (!settings.get<boolean>('Threads_enabled')) {
throw new Meteor.Error('error-not-allowed', 'Threads Disabled');
}
const { tmid } = this.bodyParams;
const thread = await Messages.findOneById(tmid, { projection: { rid: 1 } });
if (!thread?.rid) {
throw new Meteor.Error('error-invalid-message', 'Invalid Message');
}
const [user, room] = await Promise.all([
Users.findOneById(this.userId),
Rooms.findOneById(thread.rid, { projection: { ...roomAccessAttributes, t: 1, _id: 1 } }),
]);
if (!room) {
throw new Meteor.Error('error-room-does-not-exist', 'This room does not exist');
}
if (!user || !(await canAccessRoomAsync(room, user))) {
throw new Meteor.Error('error-not-allowed', 'Not Allowed');
}
await callbacks.run('beforeReadMessages', room._id, user._id);
await readThread({ user, room, tmid });
return API.v1.success();
},
)
.post(
'chat.update',
{
authRequired: true,
body: isChatUpdateProps,
response: {View on GitHub (pinned to f9d3ec372b)
Solutions
- Treat error-room-does-not-exist as a signal to drop the thread from the client (it is orphaned).
- Run a data cleanup to remove orphaned messages whose rid no longer resolves.
- Investigate room-deletion hooks if orphans recur (beforeDeleteRoom should cascade to messages).
Example fix
// before
try {
await api.readThread(tmid);
} catch (e) {
showError(e);
}
// after - gracefully drop orphaned threads
try {
await api.readThread(tmid);
} catch (e) {
if (e.error === 'error-room-does-not-exist') {
removeThreadFromUI(tmid);
return;
}
throw e;
} Defensive patterns
Strategy: try-catch
Validate before calling
async function threadRoomExists(tmid) {
const msg = await Messages.findOneById(tmid, { projection: { rid: 1 } });
if (!msg?.rid) return false;
const room = await Rooms.findOneById(msg.rid, { projection: { _id: 1 } });
return Boolean(room);
} Type guard
function hasResolvableRoom(msg, room) {
return Boolean(msg && msg.rid && room && room._id === msg.rid);
} Try / catch
try {
await api.readThread({ tmid });
} catch (e) {
if (e.error === 'error-room-does-not-exist') {
removeOrphanedThread(tmid); // room gone, drop the thread
return;
}
throw e;
} Prevention
- Drop orphaned threads (room deleted) from the client on this error.
- Run data cleanup to remove messages whose rid no longer resolves.
- Ensure beforeDeleteRoom cascades to messages to prevent orphans.
When it happens
Trigger: The thread root message exists but its room was deleted (orphan message); rid on the message points to a room id that was purged.
Common situations: Room deletion that did not clean up thread messages; data migration that dropped rooms but kept messages; replica lag in a sharded setup.
Related errors
- error-not-allowed
- error-invalid-message
- error-updatedSince-param-invalid
- Room with id ${transferData.room} not found
- Transfer to entity with id ${transferData.to} not found
AI-assisted analysis of RocketChat/Rocket.Chat@f9d3ec372b (2026-08-12).
Data as JSON: /api/errors/e15c6deac2ebd772.
Report an issue: GitHub.