RocketChat/Rocket.Chat · error · Meteor.Error

error-invalid-user

error-invalid-user

Error message

Invalid user

What it means

Thrown by the deprecated joinRoom Meteor method when Meteor.userAsync() resolves to null - no logged-in user on the connection. The method (deprecated in favor of /v1/rooms.join) needs an authenticated user to join the room, and check(rid, String) has already passed, so the failure is purely the missing session.

Source

Thrown at apps/meteor/server/meteor-methods/rooms/joinRoom.ts:24

import { Meteor } from 'meteor/meteor';

import { methodDeprecationLogger } from '../../lib/deprecationWarningLogger';

declare module '@rocket.chat/ddp-client' {
	// eslint-disable-next-line @typescript-eslint/naming-convention
	interface ServerMethods {
		joinRoom(rid: IRoom['_id'], code?: string): boolean | undefined;
	}
}

Meteor.methods<ServerMethods>({
	async joinRoom(rid, code) {
		methodDeprecationLogger.method('joinRoom', '9.0.0', '/v1/rooms.join');
		check(rid, String);

		const user = await Meteor.userAsync();
		if (!user) {
			throw new Meteor.Error('error-invalid-user', 'Invalid user', { method: 'joinRoom' });
		}

		const room = await Rooms.findOneById(rid);
		if (!room) {
			throw new Meteor.Error('error-invalid-room', 'Invalid room', { method: 'joinRoom' });
		}

		return Room.join({ room, user, ...(code ? { joinCode: code } : {}) });
	},
});

View on GitHub (pinned to b2c16d5842)

Solutions

  1. Require login before attempting the join; queue the join and execute it in Accounts.onLogin
  2. Re-authenticate when the resume token expired
  3. Migrate to POST /api/v1/rooms.join with { roomId, joinCode } and API credentials

Example fix

// before (deprecated + auth-gated)
await Meteor.callAsync('joinRoom', rid, code);

// after - REST endpoint after login
await fetch('/api/v1/rooms.join', {
  method: 'POST',
  headers: { 'X-Auth-Token': token, 'X-User-Id': uid },
  body: JSON.stringify({ roomId: rid, joinCode: code }),
});
Defensive patterns

Strategy: validation

Validate before calling

if (!Meteor.userId()) {
  // invite links: park the target room and complete the join after login
  throw new Error('login required');
}
await Meteor.callAsync('joinRoom', rid, code);

Try / catch

try {
  const joined = await Meteor.callAsync('joinRoom', rid, code);
} catch (e) {
  if (e instanceof Meteor.Error && e.error === 'error-invalid-user') {
    pendingJoin = { rid, code }; // retry once after Accounts.onLogin
    showLoginScreen();
  } else if (e instanceof Meteor.Error && e.error === 'error-invalid-room') {
    notifyRoomDeleted();
  }
}

Prevention

When it happens

Trigger: Meteor.call('joinRoom', rid, code) fired before login completes, after logout, or with an expired resume token; deep-link handlers (/invite/<rid>) that auto-join before the session is restored.

Common situations: Invite links opened by logged-out users where the join fires immediately; tab left open across a session expiry; server-side scripts invoking the DDP method without a user.

Related errors


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