{"record":{"id":"4b9773b3a83958d7","repo":"GoogleChrome/lighthouse","slug":"pluginname-has-an-invalid-category-description","errorCode":null,"errorMessage":"${pluginName} has an invalid category description.","messagePattern":"(.+?) has an invalid category description\\.","errorType":"validation","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"core/config/config-plugin.js","lineNumber":155,"sourceCode":"      throw new Error(`${pluginName} has no valid category.`);\n    }\n\n    const {\n      title,\n      description,\n      manualDescription,\n      auditRefs: auditRefsJson,\n      supportedModes,\n      ...invalidRest\n    } = categoryJson;\n\n    assertNoExcessProperties(invalidRest, pluginName, 'category');\n\n    if (!i18n.isStringOrIcuMessage(title)) {\n      throw new Error(`${pluginName} has an invalid category tile.`);\n    }\n    if (!i18n.isStringOrIcuMessage(description) && description !== undefined) {\n      throw new Error(`${pluginName} has an invalid category description.`);\n    }\n    if (!i18n.isStringOrIcuMessage(manualDescription) && manualDescription !== undefined) {\n      throw new Error(`${pluginName} has an invalid category manualDescription.`);\n    }\n    if (!isArrayOfGatherModes(supportedModes) && supportedModes !== undefined) {\n      throw new Error(\n        `${pluginName} supportedModes must be an array, ` +\n        `valid array values are \"navigation\", \"timespan\", and \"snapshot\".`\n      );\n    }\n    const auditRefs = ConfigPlugin._parseAuditRefsList(auditRefsJson, pluginName);\n\n    return {\n      title,\n      auditRefs,\n      description: description,\n      manualDescription: manualDescription,\n      supportedModes,","sourceCodeStart":137,"sourceCodeEnd":173,"githubUrl":"https://github.com/GoogleChrome/lighthouse/blob/9515cd4e58ebed69f78742d932b501c2cab8ad8f/core/config/config-plugin.js#L137-L173","documentation":"Thrown by ConfigPlugin._parseCategory while validating a Lighthouse plugin's 'category' block. The 'description' field is optional, but when present it must be a string or an i18n ICU message object (i18n.isStringOrIcuMessage). Lighthouse enforces this so every category description is renderable in the report UI. A number, boolean, array, or plain object triggers the error.","triggerScenarios":"A plugin module exports `module.exports = {category: {title: 'My Cat', description: 123, auditRefs: [...]}}`. The `description` value (123) is not undefined and fails isStringOrIcuMessage (typeof !== 'string' and not an IcuMessage), so config-plugin.js:155 throws.","commonSituations":"Authoring a custom lighthouse-plugin-* package and setting description to a non-string (e.g. an object, a number, or a YAML-parsed value that became a different type). Copying a category JSON where description was accidentally left as null or an object. Loading plugin config from JSON where a typo produced a wrong type.","solutions":["Set category.description to a plain string, e.g. description: 'Details about this category.'","If using i18n, pass an ICU message created via i18n.createMessageInstanceIdFn / UIStrings so isStringOrIcuMessage returns true.","Omit the description field entirely if you do not need it (undefined is allowed).","Check the resolved type of description after loading your plugin JSON (e.g. typeof description) before Lighthouse processes it."],"exampleFix":"// before\nmodule.exports = {\n  category: {title: 'SEO', description: {text: 'seo stuff'}, auditRefs: [{id: 'x', weight: 1}]}\n};\n// after\nmodule.exports = {\n  category: {title: 'SEO', description: 'SEO checks for the page.', auditRefs: [{id: 'x', weight: 1}]}\n};","handlingStrategy":"validation","validationCode":"// Validate a plugin category block before passing to Lighthouse\nconst i18n = require('lighthouse/core/lib/i18n/i18n.js');\nfunction validateCategory(cat) {\n  if (cat.description !== undefined && !i18n.isStringOrIcuMessage(cat.description)) {\n    throw new TypeError('category.description must be a string or IcuMessage');\n  }\n}\nvalidateCategory(plugin.category);","typeGuard":"function isStringOrUndefined(v) {\n  return v === undefined || typeof v === 'string' || (v && typeof v === 'object' && typeof v.i18nId === 'string');\n}","tryCatchPattern":"try {\n  const config = await ConfigPlugin.parsePlugin(pluginJson, name);\n} catch (e) {\n  if (/invalid category description/.test(e.message)) {\n    console.error('Fix plugin.category.description to be a string');\n  }\n  throw e;\n}","preventionTips":["Keep category text fields as plain strings or i18n message objects.","Load and type-check plugin JSON in a unit test before integrating.","Treat optional text fields as either a string or omitted, never null/number/object."],"tags":["config","lighthouse","plugin","validation","i18n"],"backgroundTag":null,"analyzedSha":"9515cd4e58ebed69f78742d932b501c2cab8ad8f","analyzedAt":"2026-08-13T06:28:10.346Z","schemaVersion":2},"datasetVersion":"2026-08-13T09:17:06.757Z"}