{"record":{"id":"fe1b4a260ca78ab1","repo":"GoogleChrome/lighthouse","slug":"plugin-name-pluginname-not-allowed-because-it","errorCode":null,"errorMessage":"plugin name '${pluginName}' not allowed because it is the id of a category already found in config","messagePattern":"plugin name '(.+?)' not allowed because it is the id of a category already found in config","errorType":"validation","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"core/config/validation.js","lineNumber":49,"sourceCode":"}\n\n/**\n * Throws if pluginName is invalid or (somehow) collides with a category in the\n * config being added to.\n * @param {LH.Config} config\n * @param {string} pluginName\n */\nfunction assertValidPluginName(config, pluginName) {\n  const parts = pluginName.split('/');\n  if (parts.length === 2) {\n    pluginName = parts[1];\n  }\n  if (!pluginName.startsWith('lighthouse-plugin-')) {\n    throw new Error(`plugin name '${pluginName}' does not start with 'lighthouse-plugin-'`);\n  }\n\n  if (config.categories?.[pluginName]) {\n    throw new Error(`plugin name '${pluginName}' not allowed because it is the id of a category already found in config`); // eslint-disable-line max-len\n  }\n}\n\n/**\n * Throws an error if the provided object does not implement the required gatherer interface.\n * @param {LH.Config.AnyArtifactDefn} artifactDefn\n */\nfunction assertValidArtifact(artifactDefn) {\n  const gatherer = artifactDefn.gatherer.instance;\n\n  if (typeof gatherer.meta !== 'object') {\n    throw new Error(`Gatherer for ${artifactDefn.id} did not provide a meta object.`);\n  }\n\n  if (gatherer.meta.supportedModes.length === 0) {\n    throw new Error(`Gatherer for ${artifactDefn.id} did not support any gather modes.`);\n  }\n","sourceCodeStart":31,"sourceCodeEnd":67,"githubUrl":"https://github.com/GoogleChrome/lighthouse/blob/9515cd4e58ebed69f78742d932b501c2cab8ad8f/core/config/validation.js#L31-L67","documentation":"Thrown by assertValidPluginName in validation.js. After confirming the prefix, Lighthouse checks the plugin name does not collide with an existing category id in the config (config.categories?.[pluginName]). A plugin becomes a category keyed by its name, so a duplicate id would overwrite an existing category. The collision is rejected.","triggerScenarios":"Config already has categories.lighthouse-plugin-foo (or a manually added category with that id) and you add plugin 'lighthouse-plugin-foo'. validation.js:49 throws because the name already maps to a category.","commonSituations":"Loading the same plugin twice. A custom config that manually defines a category whose id matches a plugin name. Plugin id clash between two plugins.","solutions":["Remove the duplicate manually-defined category that shares the plugin's id.","Rename the plugin so its id is unique among categories.","Ensure each plugin is listed only once in config.plugins."],"exampleFix":"// before\ncategories: {'lighthouse-plugin-foo': {...}},\nplugins: ['lighthouse-plugin-foo']\n// after\ncategories: {/* remove the conflicting manual category */},\nplugins: ['lighthouse-plugin-foo']","handlingStrategy":"validation","validationCode":"for (const name of config.plugins) {\n  const base = name.split('/').pop();\n  if (config.categories && config.categories[base]) {\n    throw new Error(`Plugin '${name}' collides with existing category '${base}'`);\n  }\n}","typeGuard":"function pluginNameIsUnique(name, categories) {\n  const base = name.split('/').pop();\n  return !(categories && categories[base]);\n}","tryCatchPattern":"try { await lighthouse(url, flags, config); }\ncatch (e) { if (/id of a category already found/.test(e.message)) console.error('Remove duplicate category or rename plugin'); throw e; }","preventionTips":["Avoid listing the same plugin twice.","Do not manually define a category whose id matches a plugin name.","Keep plugin names unique across the config."],"tags":["config","lighthouse","plugin","validation","categories"],"backgroundTag":null,"analyzedSha":"9515cd4e58ebed69f78742d932b501c2cab8ad8f","analyzedAt":"2026-08-13T06:28:10.346Z","schemaVersion":2},"datasetVersion":"2026-08-13T09:17:06.757Z"}