RocketChat/Rocket.Chat · error · Meteor.Error

error-invalid-user

error-invalid-user

Error message

Invalid user

What it means

Thrown by the exported deleteUserOwnAccount server helper when its first argument fromUserId is falsy (empty string, null, undefined). The helper refuses to run without a concrete user id because user lookup, credential verification, and deletion all key off it. The DDP method wrapper checks Meteor.userId() before calling, so this specific line is only reachable by direct callers of the helper (custom server code, REST bridges, tests).

Source

Thrown at apps/meteor/server/meteor-methods/users/deleteUserOwnAccount.ts:29

import { deleteUser } from '../../lib/users/deleteUser';
import { settings } from '../../settings';

declare module '@rocket.chat/ddp-client' {
	// eslint-disable-next-line @typescript-eslint/naming-convention
	interface ServerMethods {
		deleteUserOwnAccount(password: string, confirmRelinquish?: boolean): Promise<boolean>;
	}
}

export const deleteUserOwnAccount = async (fromUserId: string, password: string, confirmRelinquish = false): Promise<boolean> => {
	if (!settings.get('Accounts_AllowDeleteOwnAccount')) {
		throw new Meteor.Error('error-not-allowed', 'Not allowed', {
			method: 'deleteUserOwnAccount',
		});
	}

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

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

	if (user.services?.password && trim(user.services.password.bcrypt)) {
		const result = await Accounts._checkPasswordAsync(user as Meteor.User, {
			digest: password.toLowerCase(),
			algorithm: 'sha-256',
		});
		if (result.error) {
			throw new Meteor.Error('error-invalid-password', 'Invalid password', {

View on GitHub (pinned to b2c16d5842)

Solutions

  1. Fail fast in your wrapper: verify fromUserId is a non-empty string before invoking the helper
  2. If invoking over DDP, call Meteor.callAsync('deleteUserOwnAccount', ...) while logged in so the wrapper supplies a valid uid
  3. Map this throw to a 401-style response in your caller instead of letting error-invalid-user leak

Example fix

// before
await deleteUserOwnAccount(uidFromContext, password);

// after
if (!uidFromContext) {
	throw new Meteor.Error('error-invalid-user', 'Invalid user');
}
await deleteUserOwnAccount(uidFromContext, password);
Defensive patterns

Strategy: validation

Validate before calling

if (typeof fromUserId !== 'string' || fromUserId.trim().length === 0) {
	throw new Error('deleteUserOwnAccount: fromUserId is required');
}
await deleteUserOwnAccount(fromUserId, password, confirmRelinquish);

Type guard

const isUserId = (v: unknown): v is string => typeof v === 'string' && v.trim().length > 0;

Try / catch

try {
	await deleteUserOwnAccount(uid, password);
} catch (err) {
	if (err instanceof Meteor.Error && err.error === 'error-invalid-user') {
		// caller context had no user id — treat as unauthorized
	}
	throw err;
}

Prevention

When it happens

Trigger: Calling deleteUserOwnAccount(fromUserId, password, confirmRelinquish) server-side with fromUserId empty/undefined — e.g. an integration that resolves the caller id from a request context and forwards it without checking it resolved.

Common situations: Custom server modules importing the helper and passing an unresolved auth context; refactors that changed the first parameter; unit tests with fixtures missing the id.

Understand the failure class

Background: error-invalid-user: "Invalid user" errors in Rocket.Chat — what they mean and how to fix them — this error's family across 2 libraries.

Related errors


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