RocketChat/Rocket.Chat · error · Meteor.Error

error-invalid-room

error-invalid-room

Error message

Invalid room

What it means

Thrown by addUsersToRoomMethod() in apps/meteor/server/meteor-methods/rooms/addUsersToRoom.ts:38 when Match.test(data.rid, String) fails — data.rid is not a string (number, undefined, null, object). This is a type-shape check only; it fires before any database lookup, so the room may or may not exist.

Source

Thrown at apps/meteor/server/meteor-methods/rooms/addUsersToRoom.ts:38

export const sanitizeUsername = (username: string) => {
	const isFederatedUsername = username.includes('@') && username.includes(':');
	if (isFederatedUsername) {
		return username;
	}

	return username.replace(/(^@)|( @)/, '');
};

export const addUsersToRoomMethod = async (userId: string, data: { rid: string; users: string[] }, user?: IUser): Promise<boolean> => {
	if (!userId) {
		throw new Meteor.Error('error-invalid-user', 'Invalid user', {
			method: 'addUsersToRoom',
		});
	}

	if (!Match.test(data.rid, String)) {
		throw new Meteor.Error('error-invalid-room', 'Invalid room', {
			method: 'addUsersToRoom',
		});
	}

	// Get user and room details
	const room = await Rooms.findOneById(data.rid);
	if (!room) {
		throw new Meteor.Error('error-invalid-room', 'Invalid room', {
			method: 'addUsersToRoom',
		});
	}

	const subscription = await Subscriptions.findOneByRoomIdAndUserId(data.rid, userId, {
		projection: { _id: 1 },
	});
	const userInRoom = subscription != null;

	if (room.t === 'd' && !isRoomNativeFederated(room)) {

View on GitHub (pinned to b2c16d5842)

Solutions

  1. Ensure data.rid is a string before calling: if (typeof data.rid !== 'string') reject.
  2. Stringify ObjectIds at the boundary: String(room._id) or room._id.valueOf() when bridging from driver objects.
  3. Add a runtime schema check on the payload (e.g. Match.test(data, Match.ObjectIncluding({ rid: String, users: [String] }))) at your own entry points.
  4. For REST integrations, use POST /v1/channels.invite / POST /v1/groups.invite where room is identified by roomId and validated by the API layer.

Example fix

// before
await addUsersToRoomMethod(uid, { rid: payload.roomId?.toHexString?.() ?? payload.roomId, users });

// after
const rid = String(payload.roomId ?? '');
if (!rid) throw new Error('rid is required and must be a string');
await addUsersToRoomMethod(uid, { rid, users });
Defensive patterns

Strategy: type-guard

Validate before calling

if (!Match.test(data.rid, String)) {
  throw new Error('rid must be a string');
}

Type guard

const isRoomIdString = (v: unknown): v is string => typeof v === 'string' && v.length > 0;

Try / catch

try {
  await addUsersToRoomMethod(uid, data);
} catch (e) {
  if (e instanceof Meteor.Error && e.error === 'error-invalid-room' && typeof data.rid !== 'string') {
    // shape error: normalize rid to string before retry
  }
}

Prevention

When it happens

Trigger: Calling addUsersToRoomMethod with data.rid undefined (property misspelled or missing), a numeric ID coerced by JSON inputs, an object (e.g. passing the whole room document), or null; API/migration shims that map fields incorrectly.

Common situations: Schema drift between client payloads and the method signature; refactors renaming rid to roomId without updating all callers; JSON sources where the ID arrives as a Mongo ObjectId object rather than its string form.

Understand the failure class

Background: Invalid argument type errors: "must be of type string", "expected X, got Y", and ERR_INVALID_ARG_TYPE explained — this error's family across 15 libraries.

Related errors


AI-assisted analysis of RocketChat/Rocket.Chat@b2c16d5842 (2026-08-18). Data as JSON: /api/errors/9a1d0194ecda006a. Report an issue: GitHub.