{"record":{"id":"6bb71d4b96f10f91","repo":"GoogleChrome/lighthouse","slug":"err-message-did-not-find-the-expected-syntax","errorCode":null,"errorMessage":"[${err.message}] Did not find the expected syntax in message: ${err.originalMessage}","messagePattern":"\\[(.+?)\\] Did not find the expected syntax in message: (.+?)","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"core/scripts/i18n/collect-strings.js","lineNumber":200,"sourceCode":"\n  _ctcValidityChecks(ctc);\n\n  return ctc;\n}\n\n/**\n * Do some basic checks on an lhl message to confirm that it is valid. Future\n * lhl regression catching should go here.\n *\n * @param {string} lhlMessage\n */\nfunction _lhlValidityChecks(lhlMessage) {\n  let parsedMessageElements;\n  try {\n    parsedMessageElements = MessageParser.parse(escapeIcuMessage(lhlMessage), {ignoreTag: true});\n  } catch (err) {\n    if (err.name !== 'SyntaxError') throw err;\n    throw new Error(`[${err.message}] Did not find the expected syntax in message: ${err.originalMessage}`);\n  }\n\n  /**\n   * @param {MessageParser.MessageFormatElement[]} elements\n   */\n  function validate(elements) {\n    for (const element of elements) {\n      if (element.type === MessageParser.TYPE.plural || element.type === MessageParser.TYPE.select) {\n        // `plural`/`select` arguments can't have content before or after them.\n        // See http://userguide.icu-project.org/formatparse/messages#TOC-Complex-Argument-Types\n        // e.g. https://github.com/GoogleChrome/lighthouse/pull/11068#discussion_r451682796\n        if (elements.length > 1) {\n          throw new Error(`Content cannot appear outside plural or select ICU messages. Instead, repeat that content in each option (message: '${lhlMessage}')`);\n        }\n\n        for (const option of Object.values(element.options)) {\n          validate(option.value);\n        }","sourceCodeStart":182,"sourceCodeEnd":218,"githubUrl":"https://github.com/GoogleChrome/lighthouse/blob/9515cd4e58ebed69f78742d932b501c2cab8ad8f/core/scripts/i18n/collect-strings.js#L182-L218","documentation":"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.","triggerScenarios":"Adding a UIStrings message with unbalanced `{`, `}`, a malformed plural/select argument, or stray ICU metacharacters that are not valid placeholders, then running collect-strings.","commonSituations":"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.","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."],"exampleFix":"// before\nmessage: 'Use { or } literally'\n// after\nmessage: \"Use '{' or '}' literally\"","handlingStrategy":"try-catch","validationCode":"const {parse} = require('intl-messageformat');\nfunction isValidIcu(msg) {\n  try { parse(msg, {ignoreTag: true}); return true; } catch { return false; }\n}","typeGuard":null,"tryCatchPattern":"try {\n  _lhlValidityChecks(lhlMessage);\n} catch (e) {\n  console.error(`Invalid ICU message in ${key}: ${lhlMessage}`);\n  throw e;\n}","preventionTips":["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."],"tags":["i18n","icu","syntax-error","collect-strings","message-format"],"backgroundTag":null,"analyzedSha":"9515cd4e58ebed69f78742d932b501c2cab8ad8f","analyzedAt":"2026-08-13T06:28:10.346Z","schemaVersion":2},"datasetVersion":"2026-08-13T09:17:06.757Z"}