denoland/deno · error · Error
Linter plugin name must only contain lowercase letters…
Error message
${prefix}Linter plugin name must only contain lowercase letters (a-z) or hyphens (-). What it means
Deno's lint plugin loader validates each plugin before installing it into the linter state (installPlugin in cli/js/40_lint.js). A plugin's `name` must match /^[a-z-]+$/ — lowercase letters and hyphens only — because the name becomes part of every rule id ("plugin-name/rule-name"). This error is thrown when the name contains anything else: uppercase letters, digits, underscores, dots, or spaces. When the plugin was loaded from a specifier (the `lint.plugins` config), the message is prefixed with "Failed to load lint plugin '<specifier>': " so you can identify the misbehaving plugin.
Solutions
- Rename the plugin's `name` to lowercase letters and hyphens only, e.g. "my-plugin".
- Remove or replace the offending characters (uppercase, digits, _, ., spaces) in the exported name.
- If the name is derived from a module specifier or package name, sanitize it before exporting the plugin object.
- Re-run `deno lint` and confirm the plugin loads and its rules execute.
Example fix
// before
export default {
name: "My_Cool_Plugin",
rules: { "no-foo": { create(ctx) { return {}; } } },
};
// after
export default {
name: "my-cool-plugin",
rules: { "no-foo": { create(ctx) { return {}; } } },
}; Defensive patterns
Strategy: validation
Validate before calling
const PLUGIN_NAME_RE = /^[a-z-]+$/;
function assertValidPluginName(name) {
if (typeof name !== "string" || !PLUGIN_NAME_RE.test(name)) {
throw new Error(
`Invalid lint plugin name: ${JSON.stringify(name)} (use lowercase a-z and hyphens only)`,
);
}
} Type guard
/** @param {unknown} name @returns {boolean} */
function isValidPluginName(name) {
return typeof name === "string" && /^[a-z-]+$/.test(name);
} Try / catch
try {
await import("./my-plugin.js"); // plugin loaded via lint.plugins
} catch (err) {
// Message carries the "Failed to load lint plugin '<specifier>': " prefix
console.error(err.message);
Deno.exit(1);
} Prevention
- Adopt lowercase-kebab plugin names from the start, mirroring built-in Deno lint rule naming.
- Add a smoke test that imports each plugin and asserts /^[a-z-]+$/.test(plugin.name).
- Never derive the plugin name from a raw file path or npm package name without sanitizing.
When it happens
Trigger: A plugin installed via the lint plugin config/CLI whose default export has `name: "MyPlugin"`, `name: "plugin_1"`, `name: "plugin.name"`, or `name: "plugin 2" — any string that fails /^[a-z-]+$/. Validation happens at install time, before any file is linted.
Common situations: Porting an ESLint plugin and keeping its camelCase or PascalCase npm package name; generating the name from a file path that contains dots or digits; using underscores or spaces out of habit; copy-pasting a plugin skeleton from another ecosystem.
Related errors
- Linter plugin name must not have consequtive hyphens.
- Linter plugin name must start and end with a lowercase…
- Linter plugin rules must be an object
- Destroy hook of " " errored
- Empty node
AI-assisted analysis of denoland/deno@9ad36f7a2c (2026-08-20).
Data as JSON: /api/errors/bdb58f451906a0e6.
Report an issue: GitHub.
Appendix: source
Thrown at cli/js/40_lint.js:489
/**
* @param {Deno.lint.Plugin} plugin
* @param {string} [specifier] The specifier the plugin was loaded from, if any.
*/
function installPlugin(plugin, specifier) {
// When the plugin was loaded from a specifier (i.e. `lint.plugins` in the
// config), prefix validation errors with it so the user knows which plugin
// is misbehaving instead of getting an anonymous error.
const prefix = typeof specifier === "string"
? `Failed to load lint plugin '${specifier}': `
: "";
if (typeof plugin !== "object") {
throw new Error(`${prefix}Linter plugin must be an object`);
}
if (typeof plugin.name !== "string") {
throw new Error(`${prefix}Linter plugin name must be a string`);
}
if (!/^[a-z-]+$/.test(plugin.name)) {
throw new Error(
`${prefix}Linter plugin name must only contain lowercase letters (a-z) or hyphens (-).`,
);
}
if (plugin.name.startsWith("-") || plugin.name.endsWith("-")) {
throw new Error(
`${prefix}Linter plugin name must start and end with a lowercase letter.`,
);
}
if (plugin.name.includes("--")) {
throw new Error(
`${prefix}Linter plugin name must not have consequtive hyphens.`,
);
}
if (typeof plugin.rules !== "object") {
throw new Error(`${prefix}Linter plugin rules must be an object`);
}
if (state.installedPlugins.has(plugin.name)) {
throw new Error(`Linter plugin ${plugin.name} has already been registered`);View on GitHub (pinned to 9ad36f7a2c)