sxyazi/yazi · error

Entry name `{entry}` must be in kebab-case

Error message

Entry name `{entry}` must be in kebab-case

What it means

The same name parser as the plugin-name check also validates the entry segment (the part after the dot, defaulting to "main"). The entry name must be kebab-case; otherwise loading fails with this message. Entries map to Lua module files inside the plugin directory, so they must follow the same normalized naming rule.

Source

Thrown at yazi-runner/src/loader/loader.rs:193

	pub fn compatible_or_error(name: &str, chunk: &Chunk) -> Result<()> {
		if chunk.compatible() {
			return Ok(());
		}

		bail!(
			"Plugin `{name}` requires at least Yazi {}, but your current version is Yazi {}.",
			chunk.since,
			yazi_version::version_long()
		);
	}

	fn explode_name_parts(name: &str) -> anyhow::Result<(&str, &str, &str)> {
		let name = name.strip_suffix(".main").unwrap_or(name);
		let (plugin, entry) =
			if let Some((a, b)) = name.split_once(".") { (a, b) } else { (name, "main") };

		ensure!(plugin.as_bytes().kebab_cased(), "Plugin name `{plugin}` must be in kebab-case");
		ensure!(entry.as_bytes().kebab_cased(), "Entry name `{entry}` must be in kebab-case");
		Ok((name, plugin, entry))
	}
}

View on GitHub (pinned to 8ebf930f17)

Solutions

  1. Rename the entry reference to kebab-case (e.g., `my-plugin.MySpot` -> `my-plugin.my-spot`)
  2. Rename the entry Lua file inside the plugin directory to match kebab-case
  3. Omit the entry suffix entirely if you mean the default `.main` entry

Example fix

// before
ya.plugin("my-plugin.MySpot")
// after
ya.plugin("my-plugin.my-spot")
Defensive patterns

Strategy: validation

Validate before calling

fn is_kebab(s: &str) -> bool {
    !s.is_empty()
        && s.bytes().all(|b| b.is_ascii_lowercase() || b.is_ascii_digit() || b == b'-')
        && !s.starts_with('-') && !s.ends_with('-')
}
let (plugin, entry) = name.split_once('.').unwrap_or((name, "main"));
assert!(is_kebab(entry));

Type guard

fn valid_entry(name: &str) -> bool {
    match name.split_once('.') {
        Some((_, e)) => is_kebab(e),
        None => true, // defaults to "main"
    }
}

Try / catch

match Loader::load(name) {
    Ok(p) => p,
    Err(e) => eprintln!("plugin load failed: {e}") // message names the offending `entry`
}

Prevention

When it happens

Trigger: Loading a plugin with an explicit entry like `plugin.MyEntry` or `plugin.my_entry` where the part after the dot fails the kebab-case check; also any name containing a dot whose suffix is non-kebab-case.

Common situations: Calling a plugin entry with CamelCase or snake_case (e.g., `spotter.MySpot`), renamed entry files whose names no longer match loader expectations, or copy-pasted plugin names from docs using wrong casing.

Related errors


AI-assisted analysis of sxyazi/yazi@8ebf930f17 (2026-09-02). Data as JSON: /api/errors/cf8cafeea90ea3f2. Report an issue: GitHub.