RocketChat/Rocket.Chat · error · Meteor.Error
username-invalid
username-invalid
Error message
${_.escape(username)} is not a valid username, use only letters, numbers, dots, hyphens and underscores What it means
validateUsername() rejected the proposed name: it does not match the regex built from the UTF8_User_Names_Validation setting (default ^[0-9a-zA-Z-_.]+$ when the setting is empty or not a valid regex) — hence 'use only letters, numbers, dots, hyphens and underscores'. The check runs after the same-name early return, so it only fires for genuinely new names.
Source
Thrown at apps/meteor/server/lib/users/setUsername.ts:57
throw new Meteor.Error('error-invalid-user', 'Invalid user', { method: 'setUsername' });
}
if (isUserNativeFederated(user) || (await isUserInFederatedRooms(userId))) {
throw new Meteor.Error('error-not-allowed', 'Cannot change username for federated users or users in federated rooms', {
method: 'setUsername',
});
}
if (user.username && !settings.get('Accounts_AllowUsernameChange')) {
throw new Meteor.Error('error-not-allowed', 'Not allowed');
}
if (user.username === username || (user.username && user.username.toLowerCase() === username.toLowerCase())) {
return;
}
if (!validateUsername(username)) {
throw new Meteor.Error(
'username-invalid',
`${_.escape(username)} is not a valid username, use only letters, numbers, dots, hyphens and underscores`,
);
}
if (!(await checkUsernameAvailability(username))) {
throw new Meteor.Error('error-field-unavailable', `<strong>${_.escape(username)}</strong> is already in use :(`, {
method: 'setUsername',
field: username,
});
}
if (!(await saveUserIdentity({ _id: user._id, username }))) {
throw new Meteor.Error('error-could-not-change-username', 'Could not change username', {
method: 'setUsername',
});
}
View on GitHub (pinned to b2c16d5842)
Solutions
- Sanitize before submit: trim and strip characters outside [0-9a-zA-Z-_.] (or slugify with limax)
- If the workspace intentionally allows unicode usernames, set UTF8_User_Names_Validation to a matching regex fragment
- Mirror the active regex in client-side form validation so users get feedback before the round-trip
Example fix
// before
await setUsernameWithValidation(userId, 'josé ça-va'); // username-invalid
// after
const clean = username.trim().replace(/[^0-9a-zA-Z-_.]/g, '');
if (!/^[0-9a-zA-Z-_.]+$/.test(clean)) throw new Error('pick another name');
await setUsernameWithValidation(userId, clean); Defensive patterns
Strategy: validation
Validate before calling
// mirror the server rule (UTF8_User_Names_Validation or the default)
const USERNAME_RE = /^[0-9a-zA-Z-_.]+$/;
const clean = username.trim();
if (!USERNAME_RE.test(clean)) {
// block submit and show the allowed-charset hint
} Type guard
const isValidUsername = (v: unknown): v is string => typeof v === 'string' && /^[0-9a-zA-Z-_.]+$/.test(v.trim());
Try / catch
try {
await setUsernameWithValidation(userId, username);
} catch (error) {
if (error instanceof Meteor.Error && error.error === 'username-invalid') {
// show the allowed-charset hint next to the input
} else {
throw error;
}
} Prevention
- Never build usernames from raw email local parts or display names — sanitize first
- Keep the client-side regex in sync with UTF8_User_Names_Validation
- Trim input before validating; edge whitespace is the most common silent cause
When it happens
Trigger: Submitting a username containing spaces, accented/non-ASCII letters, emoji, or other symbols when UTF8_User_Names_Validation has not been loosened; or a name that fails a custom regex the admin installed in that setting.
Common situations: Auto-deriving usernames from email local parts or display names without sanitizing; user bases with diacritics; tightening the regex after forms were already rendered. If the setting holds an invalid regex it silently falls back to the default pattern.
Related errors
- error-input-is-not-a-valid-field
- error-blocked-username
- error-invalid-room-name
- error-setting-validation-failed
- error-setting-validation-failed
AI-assisted analysis of RocketChat/Rocket.Chat@b2c16d5842 (2026-08-18).
Data as JSON: /api/errors/c9e6b2a409d1bf8b.
Report an issue: GitHub.