GoogleChrome/lighthouse · error · Error

Unsupported locale

Error message

Unsupported locale '${requestedLocale}'

What it means

Thrown by swapLocale when the requested locale is not registered/available according to format.hasLocale. swapLocale re-renders an existing LHR into a different locale and refuses to proceed if it cannot look up the locale's messages. (A separate later guard also throws if the LHR is missing icuMessagePaths.)

Solutions

  1. Register the locale before swapping: fetch the locale JSON and call format.registerLocaleData(requestedLocale, messages).
  2. Gate the UI/locale picker on format.hasLocale so only registered locales are selectable.
  3. Fall back to the original/default locale when the requested one cannot be loaded.

Example fix

// before
const { lhr } = swapLocale(originalLhr, requestedLocale); // may throw

// after
if (format.hasLocale(requestedLocale)) {
  const { lhr } = swapLocale(originalLhr, requestedLocale);
} else {
  await registerLocaleFor(requestedLocale); // loads + registerLocaleData
}
Defensive patterns

Strategy: validation

Validate before calling

if (!format.hasLocale(requestedLocale)) {
  await ensureLocaleRegistered(requestedLocale); // fetch + registerLocaleData
}
const {lhr} = swapLocale(originalLhr, requestedLocale);

Type guard

const canSwap = (/** @type {LH.Locale} */ loc) => format.hasLocale(loc);

Try / catch

try {
  swapLocale(lhr, requestedLocale);
} catch (err) {
  if (err.message.startsWith('Unsupported locale')) {
    // fall back to original locale
  } else if (err.message === 'missing icuMessagePaths') {
    // LHR has no i18n paths; cannot swap
  } else throw err;
}

Prevention

When it happens

Trigger: Calling swapLocale(lhr, requestedLocale) where format.hasLocale(requestedLocale) is false — i.e. the locale messages were never registered via format.registerLocaleData.

Common situations: Viewer flow where fetching the locale's JSON failed silently or the locale file was not bundled; passing a locale code that Lighthouse does not ship; locale data not registered before swapLocale runs.

Related errors


AI-assisted analysis of GoogleChrome/lighthouse@9515cd4e58 (2026-08-13). Data as JSON: /api/errors/df510c79161089ca. Report an issue: GitHub.

Appendix: source

Thrown at shared/localization/swap-locale.js:52

      "audits[mainthread-work-breakdown].details.headings[1].text",
      "audits[network-rtt].details.headings[1].text",
      "audits[network-server-latency].details.headings[1].text"
    ],
    ...
 */

/**
 * Returns a new LHR with all strings changed to the new `requestedLocale`.
 * @param {LH.Result} lhr
 * @param {LH.Locale} requestedLocale
 * @return {{lhr: LH.Result, missingIcuMessageIds: string[]}}
 */
function swapLocale(lhr, requestedLocale) {
  // Copy LHR to avoid mutating provided LHR.
  lhr = JSON.parse(JSON.stringify(lhr));

  if (!format.hasLocale(requestedLocale)) {
    throw new Error(`Unsupported locale '${requestedLocale}'`);
  }
  const originalLocale = lhr.configSettings.locale;
  const {icuMessagePaths} = lhr.i18n;
  const missingIcuMessageIds = [];

  if (!icuMessagePaths) throw new Error('missing icuMessagePaths');

  for (const [i18nId, icuMessagePath] of Object.entries(icuMessagePaths)) {
    for (const instance of icuMessagePath) {
      // The path that _formatPathAsString() generated.
      let path;
      let values;
      if (typeof instance === 'string') {
        path = instance;
      } else {
        path = instance.path;
        // `values` are the string template values to be used. eg. `values: {wastedBytes: 9028}`
        values = instance.values;

View on GitHub (pinned to 9515cd4e58)