GoogleChrome/lighthouse · error
[${err.message}] Did not find the expected syntax in message
Error message
[${err.message}] Did not find the expected syntax in message: ${err.originalMessage} What it means
Thrown by _lhlValidityChecks() when the ICU MessageParser (from intl-messageformat) raises a SyntaxError while parsing an LHL message string. This means the message contains malformed ICU syntax — unbalanced braces, stray characters, or invalid placeholder/argument constructs that the parser cannot tokenize.
Source
Thrown at core/scripts/i18n/collect-strings.js:200
_ctcValidityChecks(ctc);
return ctc;
}
/**
* Do some basic checks on an lhl message to confirm that it is valid. Future
* lhl regression catching should go here.
*
* @param {string} lhlMessage
*/
function _lhlValidityChecks(lhlMessage) {
let parsedMessageElements;
try {
parsedMessageElements = MessageParser.parse(escapeIcuMessage(lhlMessage), {ignoreTag: true});
} catch (err) {
if (err.name !== 'SyntaxError') throw err;
throw new Error(`[${err.message}] Did not find the expected syntax in message: ${err.originalMessage}`);
}
/**
* @param {MessageParser.MessageFormatElement[]} elements
*/
function validate(elements) {
for (const element of elements) {
if (element.type === MessageParser.TYPE.plural || element.type === MessageParser.TYPE.select) {
// `plural`/`select` arguments can't have content before or after them.
// See http://userguide.icu-project.org/formatparse/messages#TOC-Complex-Argument-Types
// e.g. https://github.com/GoogleChrome/lighthouse/pull/11068#discussion_r451682796
if (elements.length > 1) {
throw new Error(`Content cannot appear outside plural or select ICU messages. Instead, repeat that content in each option (message: '${lhlMessage}')`);
}
for (const option of Object.values(element.options)) {
validate(option.value);
}View on GitHub (pinned to 9515cd4e58)
Solutions
- Locate the message identified in the error (err.originalMessage is printed) and fix the ICU syntax — balance all braces and escape literal braces with single quotes per ICU rules.
- If a literal `{` or `}` is needed in output, use single-quote escaping: `'{'` and `'}'`.
- Validate the message with a local ICU MessageFormat parser before committing.
Example fix
// before
message: 'Use { or } literally'
// after
message: "Use '{' or '}' literally" Defensive patterns
Strategy: try-catch
Validate before calling
const {parse} = require('intl-messageformat');
function isValidIcu(msg) {
try { parse(msg, {ignoreTag: true}); return true; } catch { return false; }
} Try / catch
try {
_lhlValidityChecks(lhlMessage);
} catch (e) {
console.error(`Invalid ICU message in ${key}: ${lhlMessage}`);
throw e;
} Prevention
- Escape literal braces with ICU single-quote syntax: '{' and '}'.
- Validate messages with intl-messageformat parser in a unit test before adding them.
- Avoid stray '#' outside plural option blocks.
When it happens
Trigger: Adding a UIStrings message with unbalanced `{`, `}`, a malformed plural/select argument, or stray ICU metacharacters that are not valid placeholders, then running collect-strings.
Common situations: Messages containing literal curly braces for display (not as ICU placeholders); copy-pasted content with special ICU characters like `#` outside plural options; hand-editing messages without escaping.
Related errors
- Content cannot appear outside plural or select ICU messages.
- must use same format and formatType for a given name. Invali
- unsupported JSDoc comment: ${JSON.stringify(comment)}
- Incorrectly formatted @example: "${rawExample}"
- Ctc messages cannot contain double dollar: ${icu.message}
AI-assisted analysis of GoogleChrome/lighthouse@9515cd4e58 (2026-08-13).
Data as JSON: /api/errors/6bb71d4b96f10f91.
Report an issue: GitHub.