{"record":{"id":"da955a16c3463918","repo":"GoogleChrome/lighthouse","slug":"uistrings-defined-in-file-but-not-exported","errorCode":null,"errorMessage":"UIStrings defined in file but not exported","messagePattern":"UIStrings defined in file but not exported","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"core/scripts/i18n/collect-strings.js","lineNumber":586,"sourceCode":"\n  for (const relativeToRootPath of files) {\n    const absolutePath = path.join(LH_ROOT, relativeToRootPath);\n    if (!process.env.CI) console.log('Collecting from', relativeToRootPath);\n\n    const content = fs.readFileSync(absolutePath, 'utf8');\n    const exportVars = await import(pathToFileURL(absolutePath).href);\n    const regexMatch = content.match(UISTRINGS_REGEX);\n    const exportedUIStrings = exportVars.UIStrings || exportVars.default?.UIStrings;\n\n    if (!regexMatch) {\n      // No UIStrings found in the file text or exports, so move to the next.\n      if (!exportedUIStrings) continue;\n\n      throw new Error('UIStrings exported but no definition found: ' + relativeToRootPath);\n    }\n\n    if (!exportedUIStrings) {\n      throw new Error('UIStrings defined in file but not exported');\n    }\n\n    // just parse the UIStrings substring to avoid ES version issues, save time, etc\n    const justUIStrings = 'const ' + regexMatch[0];\n    const parsedMessages = parseUIStrings(justUIStrings, exportedUIStrings);\n\n    for (const [key, parsed] of Object.entries(parsedMessages)) {\n      const {message, description, examples} = parsed;\n      const converted = convertMessageToCtc(message, examples);\n\n      // Don't include placeholders if there are none.\n      const placeholders = Object.keys(converted.placeholders).length === 0 ?\n          undefined :\n          converted.placeholders;\n\n      /** @type {CtcMessage} */\n      const ctc = {\n        message: converted.message,","sourceCodeStart":568,"sourceCodeEnd":604,"githubUrl":"https://github.com/GoogleChrome/lighthouse/blob/9515cd4e58ebed69f78742d932b501c2cab8ad8f/core/scripts/i18n/collect-strings.js#L568-L604","documentation":"Thrown during collection when the UISTRINGS_REGEX finds a UIStrings definition in the file text, but the module's runtime exports do not actually include UIStrings. The scanner found something that looks like a definition but it isn't exported, so messages cannot be correlated with runtime values for example/placeholder extraction.","triggerScenarios":"Defining `const UIStrings = {...}` in a file but forgetting the `export` keyword, or exporting it under a different name than `UIStrings`.","commonSituations":"Forgetting to add `export`; renaming the export but not the definition; defining UIStrings inside a function scope so it isn't a module-level export.","solutions":["Add `export` to the UIStrings definition: `export const UIStrings = {...}`.","Ensure the exported name is exactly `UIStrings`.","Confirm there is only one UIStrings definition and it is the one being exported."],"exampleFix":"// before\nconst UIStrings = {\n  myMessage: 'My message',\n};\n// after\nexport const UIStrings = {\n  myMessage: 'My message',\n};","handlingStrategy":"validation","validationCode":"function isUIStringsExported(moduleExports) {\n  return Boolean(moduleExports.UIStrings || moduleExports.default?.UIStrings);\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Always use `export const UIStrings = {...}`.","Verify the export keyword is present before running collect-strings.","Check for duplicate/shadowed UIStrings definitions."],"tags":["i18n","uistrings","export","collect-strings"],"backgroundTag":null,"analyzedSha":"9515cd4e58ebed69f78742d932b501c2cab8ad8f","analyzedAt":"2026-08-13T06:28:10.346Z","schemaVersion":2},"datasetVersion":"2026-08-13T09:17:06.757Z"}