RocketChat/Rocket.Chat · error · Meteor.Error

error-invalid-user

error-invalid-user

Error message

Invalid user

What it means

Thrown by 'saveUserProfile' when this.userId is null inside the method invocation: the DDP call carried no valid login token (or it expired). It is the standard logged-in guard, evaluated right after the Accounts_AllowUserProfileChange gate and before validateUserEditing permission checks.

Source

Thrown at apps/meteor/server/meteor-methods/users/saveUserProfile.ts:49

		realname?: string;
		newPassword?: string;
		statusText?: string;
		statusType?: string;
		bio?: string;
		nickname?: string;
	},
	customFields: Record<string, unknown>,
	..._: unknown[]
) {
	const unset: UpdateFilter<IUser> = {};
	if (!rcSettings.get<boolean>('Accounts_AllowUserProfileChange')) {
		throw new Meteor.Error('error-not-allowed', 'Not allowed', {
			method: 'saveUserProfile',
		});
	}

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

	await validateUserEditing(this.userId, {
		_id: this.userId,
		email: settings.email,
		username: settings.username,
		name: settings.realname,
		password: settings.newPassword,
		statusText: settings.statusText,
	});

	const user = await Users.findOneById(this.userId);

	if (!user) {
		throw new Meteor.Error('error-invalid-user', 'Invalid user', {
			method: 'saveUserProfile',

View on GitHub (pinned to b2c16d5842)

Solutions

  1. Guard submissions with Meteor.userId() and re-authenticate/redirect on null.
  2. Disable the form reactively when the user session ends.
  3. For server-to-server use, call PUT /api/v1/users.update with admin auth instead of the user-scoped DDP method.

Example fix

// before
submit = (data) => Meteor.callAsync('saveUserProfile', data, customFields);

// after
submit = (data) => {
  if (!Meteor.userId()) { FlowRouter.go('/login'); return; }
  Meteor.callAsync('saveUserProfile', data, customFields);
}
Defensive patterns

Strategy: validation

Validate before calling

if (!Meteor.userId()) {
  FlowRouter.go('/login');
} else {
  await Meteor.callAsync('saveUserProfile', settings, customFields);
}

Try / catch

try {
  await Meteor.callAsync('saveUserProfile', settings, customFields);
} catch (e) {
  if ((e as Meteor.Error).error === 'error-invalid-user') {
    disableForm();
    handleSessionExpired();
  }
}

Prevention

When it happens

Trigger: Calling 'saveUserProfile' after the user logged out or the resume token expired; components surviving a session reset that still submit the profile form; DDP scripts that never logged in.

Common situations: Profile form submitted after background logout; multi-tab scenarios where one tab logs out and another submits.

Related errors


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