RocketChat/Rocket.Chat · error · Error
invalid-room
Error message
invalid-room
What it means
Thrown by VideoConferenceService.create when Rooms.findOneById(rid) returns null — the room in which the call should start does not exist. This is the first guard in create, running before the caller-user and type checks, and it applies to all call types (direct, livechat, group).
Source
Thrown at apps/meteor/server/services/video-conference/service.ts:82
const { db } = MongoInternals.defaultRemoteCollectionDriver().mongo;
const logger = new Logger('VideoConference');
export class VideoConfService extends ServiceClassInternal implements IVideoConfService {
protected name = 'video-conference';
// VideoConference.create: Start a video conference using the type and provider specified as arguments
public async create(
{ type, rid, createdBy, providerName, ...data }: VideoConferenceCreateData,
useAppUser = true,
): Promise<VideoConferenceInstructions> {
return wrapExceptions(async () => {
const room = await Rooms.findOneById<Pick<IRoom, '_id' | 't' | 'uids' | 'name' | 'fname'>>(rid, {
projection: { t: 1, uids: 1, name: 1, fname: 1 },
});
if (!room) {
throw new Error('invalid-room');
}
const user = await Users.findOneById<IUser>(createdBy);
if (!user) {
throw new Error('failed-to-load-own-data');
}
if (type === 'direct') {
if (!isRoomCompatibleWithVideoConfRinging(room.t, room.uids)) {
throw new Error('type-and-room-not-compatible');
}
return this.startDirect(providerName, user, room, data);
}
if (type === 'livechat') {
return this.startLivechat(providerName, user, rid);
}View on GitHub (pinned to e4b8178b20)
Solutions
- Load the room before creating the call and abort with a clear UI message if missing
- Derive rid from a live subscription/room payload, never from a URL fragment or stale state
- Re-fetch room state when the room screen mounts so deleted rooms surface early
- Seed Rooms in test fixtures whenever seeding video conference calls
Example fix
// before
await VideoConfService.create({ type, rid, createdBy, providerName });
// after
const room = await Rooms.findOneById(rid, { projection: { t: 1, uids: 1 } });
if (!room) throw new Error('invalid-room');
await VideoConfService.create({ type, rid, createdBy, providerName }); Defensive patterns
Strategy: validation
Validate before calling
const room = await Rooms.findOneById(rid, { projection: { _id: 1 } });
if (!room) {
throw new Meteor.Error('invalid-room', 'Room not found');
} Try / catch
try {
const instructions = await VideoConfService.create(payload);
} catch (err) {
if (err instanceof Error && err.message === 'invalid-room') {
// show 'room no longer exists' and refresh the room list
}
throw err;
} Prevention
- Derive rid from a live subscription record, never from stale state
- Handle room-deleted events to close call UIs
- Validate rid format before hitting the API
When it happens
Trigger: POST video-conference/create (or the UI call button) with a rid that was deleted, mistyped, or belongs to another deployment; calling create with undefined rid because the client never loaded the room record.
Common situations: Stale room id cached by the web client after the room was deleted; tests seeding calls without seeding rooms; multi-instance setups pointing at different databases.
Understand the failure class
Background: 'Could not be found', 'does not exist', 'not found in database': the resource-not-found family when an ID, slug, key, or URI lookup comes back empty — this error's family across 20 libraries.
Related errors
- failed-to-load-own-data
- Only channels, private groups and direct messages can be cre
- Invalid user
- Message converter not found
- Room converter not found
AI-assisted analysis of RocketChat/Rocket.Chat@e4b8178b20 (2026-08-18).
Data as JSON: /api/errors/ffbcbcc5695a7035.
Report an issue: GitHub.