RocketChat/Rocket.Chat · error · Meteor.Error
error-could-not-save-identity
error-could-not-save-identity
Error message
Could not save user identity
What it means
saveUser throws error-could-not-save-identity (method 'saveUser') when saveUserIdentity returns false while applying username/name changes. False means: the target user vanished, the new username failed validateName, or _setUsername could not assign it (unavailable or blocked). saveUser aggregates all these into one error, so the underlying cause must be inferred.
Source
Thrown at apps/meteor/server/lib/users/saveUser/saveUser.ts:131
options?.auditStore?.setOriginalUser(oldUserData);
await validateUserEditing(userId, userData);
// update user
const updater = Users.getUpdater();
if (userData.hasOwnProperty('username') || userData.hasOwnProperty('name')) {
if (
!(await saveUserIdentity({
_id: userData._id,
username: userData.username,
name: userData.name,
updateUsernameInBackground: true,
updater,
session,
}))
) {
throw new Meteor.Error('error-could-not-save-identity', 'Could not save user identity', {
method: 'saveUser',
});
}
}
if (typeof userData.statusText === 'string') {
await setStatusText(oldUserData, userData.statusText, { updater, session });
}
if (userData.email) {
const shouldSendVerificationEmailToUser = userData.verified !== true;
await setEmail(userData._id, userData.email, shouldSendVerificationEmailToUser, userData.verified === true, updater);
}
if (
userData.password?.trim() &&
(await hasPermissionAsync(userId, 'edit-other-user-password')) &&
passwordPolicy.validate(userData.password)View on GitHub (pinned to b2c16d5842)
Solutions
- Pre-check availability with checkUsernameAvailability(newUsername) before calling saveUser
- Verify the new username passes the format rules (validateName) and is not in the blocked list
- If it still fails, check whether the target user still exists and inspect server logs from _setUsername for the precise refusal
Example fix
// before
await saveUser(actorId, { _id: targetId, username: 'taken.name' });
// after
const available = await checkUsernameAvailability('taken.name');
if (!available) throw new Error('Username already in use');
await saveUser(actorId, { _id: targetId, username: 'taken.name' }); Defensive patterns
Strategy: validation
Validate before calling
if (userData.username) {
const available = await checkUsernameAvailability(userData.username);
if (!available) throw new Error('Username already in use');
}
await saveUser(actorId, userData); Type guard
const isIdentitySaveError = (e: unknown): boolean =>
typeof e === 'object' && e !== null && (e as { error?: unknown }).error === 'error-could-not-save-identity'; Try / catch
try {
await saveUser(actorId, userData);
} catch (e) {
if (isIdentitySaveError(e)) {
// aggregated cause: username taken, invalid format, or user deleted — check each in order
await diagnoseIdentitySave(userData);
}
} Prevention
- Always run checkUsernameAvailability before username-bearing saves
- Treat this error as ambiguous; the definitive refusal is logged deeper in _setUsername
When it happens
Trigger: Renaming a user to an already-taken or reserved username through the admin user editor (saveUser with username set); a username with invalid characters; concurrent deletion of the target during the save.
Common situations: Admin UI rename colliding with an existing username (including case-insensitive matches); import jobs assigning names that hit the blocked list; identity sync (SAML/OAuth) pushing a name change that fails validation.
Related errors
- error-input-is-not-a-valid-field
- error-field-unavailable
- User must have a username to be banned from the room
- User not found
- error-invalid-username
AI-assisted analysis of RocketChat/Rocket.Chat@b2c16d5842 (2026-08-18).
Data as JSON: /api/errors/7b1990ab5e4f6d10.
Report an issue: GitHub.