RocketChat/Rocket.Chat · error · Meteor.Error
error-could-not-change-email
error-could-not-change-email
Error message
Could not change email
What it means
A legacy guard: thrown when setEmail(user._id, email) from server/lib/users/setEmail.ts returns falsy. In the current implementation setEmail either throws a specific error (error-invalid-email, error-field-unavailable when the address is taken, domain-blocked errors from validateEmailDomain, error-email-send-failed) or returns a truthy user object - so this branch is effectively dead code, and real failures surface as those sibling error codes instead.
Source
Thrown at apps/meteor/server/meteor-methods/users/setEmail.ts:33
}
}
export const setEmailFunction = async (email: string, user: Meteor.User | IUser) => {
check(email, String);
if (!settings.get('Accounts_AllowEmailChange')) {
throw new Meteor.Error('error-action-not-allowed', 'Changing email is not allowed', {
method: 'setEmail',
action: 'Changing_email',
});
}
if (user.emails?.[0]?.address === email) {
return email;
}
if (!(await setEmail(user._id, email))) {
throw new Meteor.Error('error-could-not-change-email', 'Could not change email', {
method: 'setEmail',
});
}
return email;
};
Meteor.methods<ServerMethods>({
async setEmail(email) {
methodDeprecationLogger.method('setEmail', '9.0.0', '/v1/users.updateOwnBasicInfo');
const user = await Meteor.userAsync();
if (!user) {
throw new Meteor.Error('error-invalid-user', 'Invalid user', { method: 'setEmail' });
}
return setEmailFunction(email, user);
},View on GitHub (pinned to b2c16d5842)
Solutions
- Catch and switch on the actual Meteor.Error code - most often error-field-unavailable (email taken) or a domain-validation error
- Verify the new address is not used by another account first (GET /api/v1/users.info?username= or email lookup) before submitting
- Treat error-could-not-change-email as an unexpected-state fallback and log err.details for diagnosis
Example fix
// before
if (err.error === 'error-could-not-change-email') showError('Could not change email');
// after
switch (err.error) {
case 'error-field-unavailable': showError('Email already in use'); break;
case 'error-invalid-email': showError('Invalid email'); break;
case 'error-email-send-failed': showError('Notification email failed'); break;
default: showError('Could not change email');
} Defensive patterns
Strategy: try-catch
Validate before calling
// avoid the common cause: check the address is not used by another account first // GET /api/v1/users.info?userId=... or a directory search before submitting the change
Try / catch
catch (err) {
if (!(err instanceof Meteor.Error)) throw err;
switch (err.error) {
case 'error-could-not-change-email': logUnexpected(err.details); break; // legacy/defensive
case 'error-field-unavailable': showFieldError('email', 'Email already in use'); break;
case 'error-invalid-email': showFieldError('email', 'Invalid email'); break;
default: throw err;
}
} Prevention
- Branch on the specific sibling error codes (error-field-unavailable, error-invalid-email, error-email-send-failed), not this legacy code
- Verify the new address is unique to the workspace before submitting
- Keep error handling in sync with the server version - this guard is effectively unreachable in current code
When it happens
Trigger: Effectively unreachable with current server code. Historically covered a generic update failure; today a failing setEmailFunction call surfaces error-field-unavailable (email already in use), a blocked-domain error, or an SMTP failure instead.
Common situations: Client code written against old behavior that branches on error-could-not-change-email; the actual thrown code differs, so error handling silently misses; documentation copied from legacy wikis.
Related errors
- error-action-not-allowed
- error-invalid-account
- error-invalid-user
- error-invalid-email
- error-password-same-as-current
AI-assisted analysis of RocketChat/Rocket.Chat@b2c16d5842 (2026-08-18).
Data as JSON: /api/errors/990e4e301063f8ff.
Report an issue: GitHub.