{"record":{"id":"17c12c4fd5eabf76","repo":"GoogleChrome/lighthouse","slug":"incorrectly-formatted-example-rawexample","errorCode":null,"errorMessage":"Incorrectly formatted @example: \"${rawExample}\"","messagePattern":"Incorrectly formatted @example: \"(.+?)\"","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"core/scripts/i18n/collect-strings.js","lineNumber":127,"sourceCode":"  // The non-string types were introduced in https://github.com/microsoft/TypeScript/pull/41877\n  // Not currently used, but utility `getTextOfJSDocComment` will convert if the types switch over.\n  if (typeof comment !== 'string') {\n    throw new Error(`unsupported JSDoc comment: ${JSON.stringify(comment)}`);\n  }\n\n  // Line breaks within a jsdoc comment should always be replaceable with a space.\n  return comment.replace(/\\n+/g, ' ').trim();\n}\n\n/**\n * Parses a string of the form `{exampleValue} placeholderName`, parsed by tsc\n * as the content of an `@example` tag.\n * @param {string} rawExample\n * @return {{placeholderName: string, exampleValue: string}}\n */\nfunction parseExampleJsDoc(rawExample) {\n  const match = rawExample.match(/^{(?<exampleValue>[^}]+)} (?<placeholderName>.+)$/);\n  if (!match || !match.groups) throw new Error(`Incorrectly formatted @example: \"${rawExample}\"`);\n  const {placeholderName, exampleValue} = match.groups;\n  return {placeholderName, exampleValue};\n}\n\n/**\n * Take a series of LHL format ICU messages and converts them\n * to CTC format by replacing {ICU} and `markdown` with\n * $placeholders$. Functional opposite of `bakePlaceholders`. This is commonly\n * called as one of the first steps in translation, via collect-strings.js.\n *\n * Converts this:\n * messages: {\n *  \"core/audits/seo/canonical.js | explanationDifferentDomain\" {\n *    \"message\": \"Points to a different domain ({url})\",\n *    },\n *  },\n * }\n *","sourceCodeStart":109,"sourceCodeEnd":145,"githubUrl":"https://github.com/GoogleChrome/lighthouse/blob/9515cd4e58ebed69f78742d932b501c2cab8ad8f/core/scripts/i18n/collect-strings.js#L109-L145","documentation":"Thrown by parseExampleJsDoc() when an @example tag's content does not match the rigid pattern `{exampleValue} placeholderName`. The i18n pipeline uses @example to declare placeholder example values, and this regex enforces that contract. Any deviation in spacing, brace placement, or missing placeholder name triggers it.","triggerScenarios":"Authoring a UIStrings entry whose @example tag is written as `{value}name` (no space), `value placeholder` (no braces), `{value}` (no placeholder name), or multiline example content that collapses to something not matching the regex.","commonSituations":"Copy-pasting example syntax from elsewhere that uses a different convention; typos in braces or forgetting the placeholder name; IDE auto-formatting stripping the required space.","solutions":["Re-read the @example tag and ensure it is exactly `{exampleValue} placeholderName` with a single space after the closing brace.","Check that exampleValue contains no `}` characters and placeholderName is non-empty.","Run collect-strings locally to surface the exact failing string before committing."],"exampleFix":"// before\n * @example {https://example.com}url\n// after\n * @example {https://example.com} url","handlingStrategy":"validation","validationCode":"const EXAMPLE_RE = /^\\{(?<exampleValue>[^}]+)} (?<placeholderName>.+)$/;\nfunction isValidExample(raw) { return EXAMPLE_RE.test(raw); }","typeGuard":"/** @param {string} raw @returns {boolean} */\nfunction isValidExampleFormat(raw) { return /^\\{[^}]+} .+$/.test(raw); }","tryCatchPattern":"if (!isValidExampleFormat(rawExample)) {\n  console.warn(`Skipping malformed @example: ${rawExample}`);\n  continue;\n}\nconst {placeholderName, exampleValue} = parseExampleJsDoc(rawExample);","preventionTips":["Always write @example as `{value} placeholderName` with exactly one space after the closing brace.","Add a lint rule or pre-commit hook that validates @example tags against the regex.","Run collect-strings locally before pushing i18n changes."],"tags":["i18n","jsdoc","example-tag","collect-strings","validation"],"backgroundTag":null,"analyzedSha":"9515cd4e58ebed69f78742d932b501c2cab8ad8f","analyzedAt":"2026-08-13T06:28:10.346Z","schemaVersion":2},"datasetVersion":"2026-08-13T09:17:06.757Z"}