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
- Send sha256(password) as a hex string exactly like the stock client does
- Verify the password is correct by re-authenticating before retrying the delete
- 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
- Hash with SHA-256 hex on the client exactly once — never send the raw password
- Do not send base64 or salted digests; the server lowercases and compares as sha-256
- Re-prompt for the password instead of auto-retrying after a failure
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.