RocketChat/Rocket.Chat · warning · Meteor.Error

moment-locale-not-found

moment-locale-not-found

Error message

Moment locale not found: ${locale}

What it means

getMomentLocale tries three bundled asset paths for the requested locale — the exact lowercased code (e.g. pt-br), the language-only prefix (pt), and a mapped variant from mapLocaleToMomentLocale (ug→ug-cn, zh→zh-cn) — and throws this Meteor.Error when none of the moment-locales/*.js assets exist. The server then cannot serve the moment.js locale file for that language.

Source

Thrown at apps/meteor/server/lib/getMomentLocale.ts:22

	ug: 'ug-cn',
	zh: 'zh-cn',
};

export async function getMomentLocale(locale: string): Promise<string | undefined> {
	const localeLower = locale.toLowerCase();
	const localesPaths = [
		`moment-locales/${localeLower}.js`,
		`moment-locales/${String(localeLower.split('-').shift())}.js`,
		`moment-locales/${mapLocaleToMomentLocale[localeLower]}.js`,
	];
	for await (const localePath of localesPaths) {
		try {
			return await Assets.getTextAsync(localePath);
		} catch (error) {
			continue;
		}
	}
	throw new Meteor.Error('moment-locale-not-found', `Moment locale not found: ${locale}`);
}

View on GitHub (pinned to b2c16d5842)

Solutions

  1. Use a supported language/locale code for the setting that feeds getMomentLocale
  2. For custom locales, add the moment-locales/<locale>.js server asset and, when the moment name differs, an entry in mapLocaleToMomentLocale
  3. As a caller, catch this error and fall back to the 'en' locale

Example fix

// before
const localeSrc = await getMomentLocale(locale);

// after
let localeSrc: string | undefined;
try {
  localeSrc = await getMomentLocale(locale);
} catch (err) {
  if (err instanceof Meteor.Error && err.error === 'moment-locale-not-found') {
    localeSrc = await getMomentLocale('en');
  } else {
    throw err;
  }
}
Defensive patterns

Strategy: fallback

Validate before calling

const SUPPORTED_MOMENT_LOCALES = ['en', 'de', 'pt-br', 'zh-cn' /* ... */];
const localeLower = locale.toLowerCase();
const safeLocale = SUPPORTED_MOMENT_LOCALES.includes(localeLower) ? locale : 'en';

Try / catch

try {
  return await getMomentLocale(locale);
} catch (err) {
  if (err instanceof Meteor.Error && err.error === 'moment-locale-not-found') {
    return getMomentLocale('en'); // graceful degradation to default locale
  }
  throw err;
}

Prevention

When it happens

Trigger: A user's language resolves to a locale code with no matching bundled moment asset: unsupported/odd region variants, or custom language packs that added translations but no moment locale file and no mapLocaleToMomentLocale entry.

Common situations: Custom locale added without shipping the moment asset or updating the mapping; deployments where server assets are incomplete; clients requesting unusual Accept-Language variants.

Related errors


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