{"record":{"id":"5a9bd8f72abb7be3","repo":"GoogleChrome/lighthouse","slug":"unsupported-jsdoc-comment-json-stringify-commen","errorCode":null,"errorMessage":"unsupported JSDoc comment: ${JSON.stringify(comment)}","messagePattern":"unsupported JSDoc comment: (.+?)","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"core/scripts/i18n/collect-strings.js","lineNumber":112,"sourceCode":"\n  if (ast.comment) {\n    // The entire comment is the description, so return everything.\n    return {description: coerceToSingleLineAndTrim(ast.comment), examples: {}};\n  }\n\n  throw Error(`Missing description comment for message \"${message}\"`);\n}\n\n/**\n * Collapses a jsdoc comment into a single line and trims whitespace.\n * @param {import('typescript').JSDoc['comment']} comment\n * @return {string}\n */\nfunction coerceToSingleLineAndTrim(comment = '') {\n  // 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}","sourceCodeStart":94,"sourceCodeEnd":130,"githubUrl":"https://github.com/GoogleChrome/lighthouse/blob/9515cd4e58ebed69f78742d932b501c2cab8ad8f/core/scripts/i18n/collect-strings.js#L94-L130","documentation":"Thrown by coerceToSingleLineAndTrim() when a JSDoc comment value passed from the TypeScript compiler API is not a string. Per TS PR #41877, JSDoc comments can theoretically be string | string[] | undefined, but this i18n collection script currently only handles the string form. If a future TypeScript version starts returning array/structured comments for certain JSDoc constructs, this guard fires.","triggerScenarios":"Running `node core/scripts/i18n/collect-strings.js` after upgrading TypeScript, or authoring a JSDoc annotation that TypeScript parses into a non-string comment node (e.g. multi-part structured comments introduced by a newer TS API).","commonSituations":"TypeScript major-version bumps that change the JSDoc comment node shape; exotic JSDoc tags or inline link structures that tsc represents as arrays rather than plain strings.","solutions":["Pin or downgrade TypeScript to the version the project currently uses (check package.json / devDependencies).","If upgrading intentionally, update coerceToSingleLineAndTrim to handle string[] by joining elements, mirroring TS utility getTextOfJSDocComment.","Inspect the offending JSDoc block in the source file reported upstream and simplify it to a plain single-line comment."],"exampleFix":"// before\nif (typeof comment !== 'string') {\n  throw new Error(`unsupported JSDoc comment: ${JSON.stringify(comment)}`);\n}\n// after\nif (Array.isArray(comment)) {\n  comment = comment.map(c => typeof c === 'string' ? c : c.text).join(' ');\n}\nif (typeof comment !== 'string') {\n  throw new Error(`unsupported JSDoc comment: ${JSON.stringify(comment)}`);\n}","handlingStrategy":"type-guard","validationCode":"// Before calling coerceToSingleLineAndTrim, normalize the comment:\nfunction normalizeJSDocComment(comment) {\n  if (Array.isArray(comment)) return comment.map(c => typeof c === 'string' ? c : c.text).join(' ');\n  if (typeof comment === 'object' && comment !== null && 'text' in comment) return comment.text;\n  if (typeof comment === 'string') return comment;\n  return '';\n}","typeGuard":"/** @param {unknown} c @returns {c is string} */\nfunction isStringComment(c) { return typeof c === 'string'; }","tryCatchPattern":"try {\n  return coerceToSingleLineAndTrim(jsdoc.comment);\n} catch (e) {\n  if (/unsupported JSDoc comment/.test(e.message)) return '';\n  throw e;\n}","preventionTips":["Pin the TypeScript version in devDependencies to avoid JSDoc node-shape changes.","Write JSDoc descriptions as simple single-line strings.","If upgrading TypeScript, run collect-strings in CI to catch regressions early."],"tags":["i18n","jsdoc","typescript-compat","collect-strings"],"backgroundTag":null,"analyzedSha":"9515cd4e58ebed69f78742d932b501c2cab8ad8f","analyzedAt":"2026-08-13T06:28:10.346Z","schemaVersion":2},"datasetVersion":"2026-08-13T09:17:06.757Z"}