RocketChat/Rocket.Chat · error · Meteor.Error

error-invalid-user

error-invalid-user

Error message

Invalid user

What it means

saveUser's internal findUserById throws error-invalid-user when the acting user (the id passed as the first argument, used as 'performedBy' for audit) does not exist. This fires before any validation of the payload: the caller of saveUser must be a real user record.

Source

Thrown at apps/meteor/server/lib/users/saveUser/saveUser.ts:68

	joinDefaultChannels?: boolean;
	sendWelcomeEmail?: boolean;

	customFields?: Record<string, any>;
	active?: boolean;

	freeSwitchExtension?: string;
};
export type UpdateUserData = RequiredField<SaveUserData, '_id'>;
export const isUpdateUserData = (params: SaveUserData): params is UpdateUserData => '_id' in params && !!params._id;

type SaveUserOptions = {
	auditStore?: UserChangedAuditStore;
};

const findUserById = async (uid: IUser['_id']): Promise<IUser> => {
	const user = await Users.findOneById(uid);
	if (!user) {
		throw new Meteor.Error('error-invalid-user', 'Invalid user');
	}

	return user;
};

const _saveUser = (session?: ClientSession) =>
	async function (userId: IUser['_id'], userData: SaveUserData, options?: SaveUserOptions) {
		const performedBy = await findUserById(userId);

		const oldUserData = userData._id && (await Users.findOneById(userData._id));
		if (oldUserData && isUserFederated(oldUserData)) {
			throw new Meteor.Error('Edit_Federated_User_Not_Allowed', 'Not possible to edit a federated user');
		}

		await validateUserData(userId, userData);

		await callbacks.run('beforeSaveUser', {
			user: userData,

View on GitHub (pinned to b2c16d5842)

Solutions

  1. Confirm the acting userId exists (Users.findOneById) before calling saveUser
  2. In request-driven code, take the actor from the authenticated session instead of a parameter
  3. In tests, seed the acting user first
Defensive patterns

Strategy: validation

Validate before calling

const actor = await Users.findOneById(actorId, { projections: { _id: 1 } });
if (!actor) throw new Error('Acting user does not exist');
await saveUser(actorId, userData);

Try / catch

try {
  await saveUser(actorId, userData);
} catch (e) {
  if (isMeteorErrorCode(e, 'error-invalid-user')) {
  	// actor id is wrong/stale: re-resolve from the authenticated session
  }
}

Prevention

When it happens

Trigger: Calling saveUser(userId, userData) with a stale, deleted, or fabricated actor id; server code invoking saveUser with a request context whose user was removed between authentication and the save.

Common situations: Automation passing a hard-coded admin id that differs per environment; the acting admin's account deleted mid-session; tests without seeded users.

Related errors


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