{"record":{"id":"bdb58f451906a0e6","repo":"denoland/deno","slug":"prefix-linter-plugin-name-must-only-contain-lowe","errorCode":null,"errorMessage":"${prefix}Linter plugin name must only contain lowercase letters (a-z) or hyphens (-).","messagePattern":"(.+?)Linter plugin name must only contain lowercase letters \\(a-z\\) or hyphens \\(-\\)\\.","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"cli/js/40_lint.js","lineNumber":489,"sourceCode":"/**\n * @param {Deno.lint.Plugin} plugin\n * @param {string} [specifier] The specifier the plugin was loaded from, if any.\n */\nfunction installPlugin(plugin, specifier) {\n  // When the plugin was loaded from a specifier (i.e. `lint.plugins` in the\n  // config), prefix validation errors with it so the user knows which plugin\n  // is misbehaving instead of getting an anonymous error.\n  const prefix = typeof specifier === \"string\"\n    ? `Failed to load lint plugin '${specifier}': `\n    : \"\";\n  if (typeof plugin !== \"object\") {\n    throw new Error(`${prefix}Linter plugin must be an object`);\n  }\n  if (typeof plugin.name !== \"string\") {\n    throw new Error(`${prefix}Linter plugin name must be a string`);\n  }\n  if (!/^[a-z-]+$/.test(plugin.name)) {\n    throw new Error(\n      `${prefix}Linter plugin name must only contain lowercase letters (a-z) or hyphens (-).`,\n    );\n  }\n  if (plugin.name.startsWith(\"-\") || plugin.name.endsWith(\"-\")) {\n    throw new Error(\n      `${prefix}Linter plugin name must start and end with a lowercase letter.`,\n    );\n  }\n  if (plugin.name.includes(\"--\")) {\n    throw new Error(\n      `${prefix}Linter plugin name must not have consequtive hyphens.`,\n    );\n  }\n  if (typeof plugin.rules !== \"object\") {\n    throw new Error(`${prefix}Linter plugin rules must be an object`);\n  }\n  if (state.installedPlugins.has(plugin.name)) {\n    throw new Error(`Linter plugin ${plugin.name} has already been registered`);","sourceCodeStart":471,"sourceCodeEnd":507,"githubUrl":"https://github.com/denoland/deno/blob/89f33cbef296a2b287f323d42de54c871fa69c77/cli/js/40_lint.js#L471-L507","documentation":"Thrown by installPlugin() in cli/js/40_lint.js when a Deno lint plugin's `name` fails the /^[a-z-]+$/ check. Plugin names are used to build rule ids like `plugin-name/rule-name`, so they must be strictly lowercase ASCII letters and single hyphens; the regex also rejects an empty name. When the plugin came from a `lint.plugins` entry in the config, the message is prefixed with the specifier so you know which file is at fault.","triggerScenarios":"A plugin object whose `name` contains uppercase letters (\"myPlugin\"), digits (\"plugin2\"), underscores (\"my_plugin\"), whitespace, non-ASCII characters, or is the empty string \"\". Reached via `lint.plugins` in deno.json or programmatic plugin installation before any linting runs.","commonSituations":"Porting an ESLint plugin to a Deno lint plugin and keeping a camelCase or snake_case name; copying a plugin file and renaming it with a version suffix like \"my-plugin-2\"; forgetting the name field and defaulting it to \"\".","solutions":["Rename the plugin to lowercase letters and single hyphens, e.g. \"my-plugin\"","If the name came from a config-loaded plugin, check the 'Failed to load lint plugin \\'<specifier>\\':' prefix to find the offending file","Keep the name non-empty, starting/ending with a letter, with no consecutive hyphens (the following checks also apply)"],"exampleFix":"// before\nexport default {\n  name: \"myLintPlugin\",\n  rules: { /* ... */ },\n};\n\n// after\nexport default {\n  name: \"my-lint-plugin\",\n  rules: { /* ... */ },\n};","handlingStrategy":"validation","validationCode":"const NAME_RE = /^[a-z]+(?:-[a-z]+)*$/; // charset + edges + no doubles\nfunction assertValidPluginName(name) {\n  if (typeof name !== \"string\") throw new TypeError(\"plugin.name must be a string\");\n  if (!NAME_RE.test(name)) {\n    throw new TypeError(\n      `invalid plugin name '${name}': use lowercase letters and single inner hyphens`,\n    );\n  }\n}\n// run before registering / shipping the plugin\nassertValidPluginName(plugin.name);","typeGuard":"function isValidLintPluginName(name) {\n  return typeof name === \"string\" && /^[a-z]+(?:-[a-z]+)*$/.test(name);\n}","tryCatchPattern":null,"preventionTips":["Derive plugin names from the package name early and never hand-edit them per rule","Add a unit test that validates your plugin object's shape (name + rules) so mis-edits fail in your CI, not in users' lint runs","Run `deno lint` once on a scratch file as a smoke test after any plugin edit"],"tags":["lint","plugin","validation","naming","config"],"backgroundTag":null,"analyzedSha":"89f33cbef296a2b287f323d42de54c871fa69c77","analyzedAt":"2026-08-16T07:54:21.310Z","schemaVersion":2},"datasetVersion":"2026-08-16T08:17:34.114Z"}