GoogleChrome/lighthouse · error · Error
Unsupported locale '${requestedLocale}'
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.)
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)
Solutions
- Register the locale before swapping: fetch the locale JSON and call format.registerLocaleData(requestedLocale, messages).
- Gate the UI/locale picker on format.hasLocale so only registered locales are selectable.
- 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
- Register locale data (registerLocaleData) before invoking swapLocale.
- Restrict the locale picker to locales for which format.hasLocale is true.
- Treat a failed locale fetch as 'locale unavailable' and keep the current locale.
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
- Unsupported locale '${locale}'
- could not fetch data for locale: ${locale}
- expected locale file to exist: ${traceEnginePath}
- Invalid value: Argument 'locale' must be a string
- ${pluginName} has an invalid category description.
AI-assisted analysis of GoogleChrome/lighthouse@9515cd4e58 (2026-08-13).
Data as JSON: /api/errors/df510c79161089ca.
Report an issue: GitHub.