RocketChat/Rocket.Chat · error · MeteorError

error-code-invalid

error-code-invalid

Error message

Invalid code

What it means

The join-code branch of join() validates the supplied code with Rooms.findOneByJoinCodeAndId(joinCode, room._id); if no room matches, the code is wrong for this room and join throws Meteor error-code-invalid ('Invalid code', method 'joinRoom').

Source

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

		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);
	}

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

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

View on GitHub (pinned to b2c16d5842)

Solutions

  1. Trim/verify the input and re-check the code with the room owner, then re-submit exactly
  2. Owners can reset the room's join code and re-share it
  3. Grant join-without-join-code to trusted roles to avoid code handling entirely

Example fix

// before
await roomService.join({ room, user, joinCode: codeFromUser });

// after
const joinCode = codeFromUser?.trim();
if (!joinCode) throw new Error('error-code-required');
await roomService.join({ room, user, joinCode });
Defensive patterns

Strategy: try-catch

Validate before calling

const joinCode = rawInput?.trim();
if (!joinCode) throw new Error('error-code-required');
const matches = await Rooms.findOneByJoinCodeAndId(joinCode, room._id, { projections: { _id: 1 } });
if (!matches) {
  // wrong code: re-prompt instead of calling join() and failing
  return rePromptForJoinCode(room);
}

Type guard

const isValidJoinCode = async (joinCode: string, roomId: string): Promise<boolean> =>
  Boolean(await Rooms.findOneByJoinCodeAndId(joinCode.trim(), roomId, { projections: { _id: 1 } }));

Try / catch

try {
  await roomService.join({ room, user, joinCode });
} catch (err) {
  if (err?.error === 'error-code-invalid') {
    // re-prompt with a fresh attempt limit; do not auto-retry the same code
    return rePromptForJoinCode(room);
  }
  throw err;
}

Prevention

When it happens

Trigger: Submitting an incorrect or outdated join code for a join-code-protected room: typos, codes rotated by owners, or copy/paste artifacts (extra whitespace).

Common situations: Owners changed the code after it was shared; users pasting codes with trailing spaces; case mismatches.

Related errors


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