RocketChat/Rocket.Chat · error · Meteor.Error

error-invalid-user

error-invalid-user

Error message

Invalid user

What it means

Thrown by the deprecated `unblockUser` Meteor method when `Meteor.userId()` is falsy, meaning the method ran without an authenticated user bound to the DDP invocation. The guard exists because `unblockUserMethod(userId, { rid, blocked })` unblocks a user in a room on behalf of a specific caller, so an identity is mandatory. The method is deprecated since 9.0.0 in favor of the REST endpoint `POST /v1/im.blockUser` (it logs a deprecation warning on every call).

Source

Thrown at apps/meteor/server/meteor-methods/users/unblockUser.ts:24

import { unblockUserMethod } from '../../lib/users/unblockUser';

declare module '@rocket.chat/ddp-client' {
	// eslint-disable-next-line @typescript-eslint/naming-convention
	interface ServerMethods {
		unblockUser({ rid, blocked }: { rid: string; blocked: string }): boolean;
	}
}

Meteor.methods<ServerMethods>({
	async unblockUser({ rid, blocked }) {
		methodDeprecationLogger.method('unblockUser', '9.0.0', '/v1/im.blockUser');
		check(rid, String);
		check(blocked, String);

		const userId = Meteor.userId();

		if (!userId) {
			throw new Meteor.Error('error-invalid-user', 'Invalid user', { method: 'unblockUser' });
		}

		await unblockUserMethod(userId, { rid, blocked });

		return true;
	},
});

View on GitHub (pinned to b2c16d5842)

Solutions

  1. Log in (or resume the session) on the connection before invoking the method, and check `Meteor.userId()` client-side first.
  2. In server code, skip the method wrapper and call `unblockUserMethod(userId, { rid, blocked })` directly (from `apps/meteor/server/lib/users/unblockUser`) with a known userId.
  3. Migrate to `POST /v1/im.blockUser` with `X-Auth-Token` / `X-User-Id` headers — the method is scheduled for removal in 9.0.0.

Example fix

// before (server-side, no user bound to the invocation)
Meteor.call('unblockUser', { rid, blocked });

// after — call the underlying API directly with a known userId
import { unblockUserMethod } from '../../lib/users/unblockUser';
await unblockUserMethod(userId, { rid, blocked });
Defensive patterns

Strategy: validation

Validate before calling

const userId = Meteor.userId();
if (!userId) {
  throw new Error('Login required before unblocking a user');
}
Meteor.call('unblockUser', { rid, blocked });

Try / catch

Meteor.call('unblockUser', { rid, blocked }, (err, res) => {
  if (err && err.error === 'error-invalid-user') {
    // session lost: re-authenticate, then retry once
    return;
  }
  if (err) throw err;
  // use res
});

Prevention

When it happens

Trigger: Calling `Meteor.call('unblockUser', { rid, blocked })` from a logged-out client; invoking the method in server-side code where no user is bound to the invocation context (raw `Meteor.call` on the server has no userId); a raw DDP method call without a resumed login token.

Common situations: Server-side scripts or migrations calling client-facing methods without user context; sessions that expired between page load and the call; automated tests that forget to log a user in; integrations that should be using the REST API with an auth token instead of DDP methods.

Related errors


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