RocketChat/Rocket.Chat · error · Error

error-invalid-user

Error message

error-invalid-user

What it means

Thrown by GET /api/v1/livechat/room.join when this.user is falsy. The route is authRequired, so an auth failure normally 401s earlier; reaching this throw means authentication succeeded (userId resolved) but the user document could not be loaded — a server-side inconsistency rather than a normal client mistake.

Solutions

  1. Log out and re-authenticate to obtain a fresh token for a valid user
  2. Verify the user still exists and is active (login works) on the same instance
  3. If it reproduces for an existing user, inspect server logs and the users collection — treat as a data-integrity incident
Defensive patterns

Strategy: try-catch

Validate before calling

const me = await (await fetch(`${url}/api/v1/me`, { headers: authHeaders })).json();
if (!me?._id || !me.username) { await reAuthenticate(); return; }

Type guard

function isAuthenticatedUser(u) {
  return Boolean(u) && typeof u._id === 'string';
}

Try / catch

try { await joinRoom(roomId); } catch (e) { if (e.message === 'error-invalid-user') { await reAuthenticate(); return joinRoom(roomId); } throw e; }

Prevention

When it happens

Trigger: Authenticated request whose user record is missing/unreadable at lookup time: user deleted between token validation and handler execution, partially-migrated user data, or an auth token referencing a stale user id.

Common situations: User deleted/deactivated while its token was still cached in a client; database restores or user-management sync jobs; very rare on healthy installs.

Related errors


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

Appendix: source

Thrown at apps/meteor/server/api/v1/omnichannel/room.ts:412

);

type LivechatAnalyticsEndpoints = ExtractRoutesFromAPI<typeof livechatVisitorDepartmentTransfer>;
declare module '@rocket.chat/rest-typings' {
	// eslint-disable-next-line @typescript-eslint/naming-convention, @typescript-eslint/no-empty-interface
	interface Endpoints extends LivechatAnalyticsEndpoints {}
}

API.v1.addRoute(
	'livechat/room.join',
	{ authRequired: true, permissionsRequired: ['view-l-room'], validateParams: isLiveChatRoomJoinProps },
	{
		async get() {
			const { roomId } = this.queryParams;

			const { user } = this;

			if (!user) {
				throw new Error('error-invalid-user');
			}

			const room = await LivechatRooms.findOneById(roomId);

			if (!room) {
				throw new Error('error-invalid-room');
			}

			if (!room.open) {
				throw new Error('room-closed');
			}

			if (!(await Omnichannel.isWithinMACLimit(room))) {
				throw new Error('error-mac-limit-reached');
			}

			if (!(await canAccessRoomAsync(room, user))) {
				throw new Error('error-not-allowed');

View on GitHub (pinned to b2c16d5842)