RocketChat/Rocket.Chat · error · Meteor.Error

error-invalid-password

error-invalid-password

Error message

Invalid password

What it means

The account has a local password (services.password.bcrypt non-empty) and Accounts._checkPasswordAsync rejected the credential with error-invalid-password. The password argument is not the raw password: the server lowercases it and compares it as a sha-256 digest against bcrypt, so the client must send SHA256(password) in hex. Any wrong password or wrong digest scheme fails here.

Source

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

		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', {
				method: 'deleteUserOwnAccount',
			});
		}
	} else if (!user.username || SHA256(user.username) !== password.trim()) {
		throw new Meteor.Error('error-invalid-username', 'Invalid username', {
			method: 'deleteUserOwnAccount',
		});
	}

	await deleteUser(fromUserId, confirmRelinquish);

	// App IPostUserDeleted event hook
	await Apps.self?.triggerEvent(AppEvents.IPostUserDeleted, { user });

	return true;
};

Meteor.methods<ServerMethods>({

View on GitHub (pinned to b2c16d5842)

Solutions

  1. Send sha256(password) as a hex string exactly like the stock client does
  2. Verify the password is correct by re-authenticating before retrying the delete
  3. If the password was recently changed, re-prompt and re-hash before the call

Example fix

// before — raw password sent
await Meteor.callAsync('deleteUserOwnAccount', myPassword, false);

// after — hex sha256 digest
const digest = SHA256(myPassword).toString();
await Meteor.callAsync('deleteUserOwnAccount', digest, false);
Defensive patterns

Strategy: try-catch

Validate before calling

// client: always send the digest the server expects
const digest = SHA256(password).toString(); // hex, lowercase-safe
await Meteor.callAsync('deleteUserOwnAccount', digest, false);

Try / catch

try {
	await Meteor.callAsync('deleteUserOwnAccount', digest, false);
} catch (err) {
	if ((err as { error?: string }).error === 'error-invalid-password') {
		// wrong password or wrong digest scheme — re-prompt, do not retry blindly
	}
}

Prevention

When it happens

Trigger: Wrong password entered; or a custom client sending the plaintext password, a base64 digest, or any non-sha256-hex value instead of the hex sha256 digest the stock client computes.

Common situations: Custom clients that skip the client-side SHA-256 hashing step; password changed after the page loaded; users typing the wrong credential on the delete-confirmation dialog.

Related errors


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