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

  1. Sanitize before submit: trim and strip characters outside [0-9a-zA-Z-_.] (or slugify with limax)
  2. If the workspace intentionally allows unicode usernames, set UTF8_User_Names_Validation to a matching regex fragment
  3. 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

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


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