RocketChat/Rocket.Chat · error · MeteorError

error-code-required

error-code-required

Error message

Code required

What it means

In join(), rooms protected by a join code (isRoomWithJoinCode) require a joinCode argument unless the user holds the join-without-join-code permission. When no joinCode is passed and the permission is absent, join throws Meteor error-code-required ('Code required', method 'joinRoom').

Source

Thrown at apps/meteor/server/services/room/service.ts:207

		if (isOmnichannelRoom(room) && !room.open) {
			throw new MeteorError('room-closed', 'Room is closed', { method: 'joinRoom' });
		}

		if (!(await Authorization.canAccessRoom(room, user))) {
			throw new MeteorError('error-not-allowed', 'Not allowed', { method: 'joinRoom' });
		}

		if (
			FederationActions.shouldPerformFederationAction(room) &&
			!isUserNativeFederated(user) &&
			!(await FederationMatrix.canUserAccessFederation(user))
		) {
			throw new MeteorError('error-not-authorized-federation', 'Not authorized to access federation', { method: 'joinRoom' });
		}

		if (isRoomWithJoinCode(room) && !(await Authorization.hasPermission(user._id, 'join-without-join-code'))) {
			if (!joinCode) {
				throw new MeteorError('error-code-required', 'Code required', { method: 'joinRoom' });
			}

			const isCorrectJoinCode = !!(await Rooms.findOneByJoinCodeAndId(joinCode, room._id, {
				projection: { _id: 1 },
			}));

			if (!isCorrectJoinCode) {
				throw new MeteorError('error-code-invalid', 'Invalid code', { method: 'joinRoom' });
			}
		}

		return addUserToRoom(room._id, user);
	}

	async beforeLeave(room: IRoom): Promise<void> {
		FederationActions.blockIfRoomFederatedButServiceNotReady(room);
	}

View on GitHub (pinned to b2c16d5842)

Solutions

  1. Prompt the user for the room's join code and pass it as joinCode
  2. Grant the role join-without-join-code where policy allows bypassing codes
  3. Confirm the room actually requires a code (isRoomWithJoinCode) before demanding input
Defensive patterns

Strategy: validation

Validate before calling

import { Authorization } from '@rocket.chat/core-services';

const needsCode = isRoomWithJoinCode(room) && !(await Authorization.hasPermission(uid, 'join-without-join-code'));
if (needsCode && !joinCode) {
  // prompt for the code instead of calling join() without it
  return promptForJoinCode(room);
}

Type guard

const requiresJoinCode = async (room: IRoom, uid: string): Promise<boolean> =>
  isRoomWithJoinCode(room) && !(await Authorization.hasPermission(uid, 'join-without-join-code'));

Try / catch

try {
  await roomService.join({ room, user });
} catch (err) {
  if (err?.error === 'error-code-required') {
    // ask for the code, then retry once with joinCode supplied
    const joinCode = await promptForJoinCode(room);
    return roomService.join({ room, user, joinCode });
  }
  throw err;
}

Prevention

When it happens

Trigger: Calling join({ room, user }) with no joinCode on a join-code-protected room while the user lacks join-without-join-code.

Common situations: Clients not surfacing the join-code prompt; scripts/integrations calling join without a code; permission changes removing the bypass from a role.

Related errors


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