{"record":{"id":"b585893e660ed15c","repo":"GoogleChrome/lighthouse","slug":"plugin-name-pluginname-does-not-start-with-l","errorCode":null,"errorMessage":"plugin name '${pluginName}' does not start with 'lighthouse-plugin-'","messagePattern":"plugin name '(.+?)' does not start with 'lighthouse-plugin-'","errorType":"validation","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"core/config/validation.js","lineNumber":45,"sourceCode":"  // A snapshot artifact cannot depend on a timespan/navigation artifact because it might run without a timespan.\n  if (dependentLevel === levels.snapshot) return dependencyLevel === levels.snapshot;\n  // A navigation artifact can depend on anything.\n  return true;\n}\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","sourceCodeStart":27,"sourceCodeEnd":63,"githubUrl":"https://github.com/GoogleChrome/lighthouse/blob/9515cd4e58ebed69f78742d932b501c2cab8ad8f/core/config/validation.js#L27-L63","documentation":"Thrown by assertValidPluginName in validation.js. A Lighthouse plugin's name must begin with the prefix 'lighthouse-plugin-'. An optional npm scope prefix (one '/') is stripped first, so '@scope/lighthouse-plugin-foo' is allowed. Any name not starting with the required prefix after scope-stripping is rejected, so plugins are namespaced predictably.","triggerScenarios":"Adding plugin 'my-plugin' or '@scope/my-plugin' to config.plugins. After splitting on '/', the name does not start with 'lighthouse-plugin-', so validation.js:45 throws.","commonSituations":"Forgetting the required 'lighthouse-plugin-' prefix when naming/publishing a plugin. Using a short alias in plugins array. Mismatch between the npm package name and the plugin name Lighthouse expects.","solutions":["Name/publish the plugin with the prefix: 'lighthouse-plugin-myplugin' (or '@scope/lighthouse-plugin-myplugin').","Update config.plugins to use the prefixed name exactly.","Ensure the package's main export also uses the prefixed id internally."],"exampleFix":"// before\nplugins: ['my-plugin']\n// after\nplugins: ['lighthouse-plugin-myplugin']","handlingStrategy":"validation","validationCode":"function assertPluginName(name) {\n  const base = name.split('/').pop();\n  if (!base.startsWith('lighthouse-plugin-')) {\n    throw new Error(`Plugin '${name}' must start with 'lighthouse-plugin-'`);\n  }\n}\nconfig.plugins.forEach(assertPluginName);","typeGuard":"function isValidPluginName(name) {\n  const parts = name.split('/');\n  const base = parts.length === 2 ? parts[1] : name;\n  return base.startsWith('lighthouse-plugin-');\n}","tryCatchPattern":"try { await lighthouse(url, flags, config); }\ncatch (e) { if (/does not start with 'lighthouse-plugin-'/.test(e.message)) console.error('Rename plugin with the required prefix'); throw e; }","preventionTips":["Prefix all plugin package names with 'lighthouse-plugin-'.","Validate plugin names in config before invoking Lighthouse."],"tags":["config","lighthouse","plugin","validation","naming"],"backgroundTag":null,"analyzedSha":"9515cd4e58ebed69f78742d932b501c2cab8ad8f","analyzedAt":"2026-08-13T06:28:10.346Z","schemaVersion":2},"datasetVersion":"2026-08-13T09:17:06.757Z"}