{"record":{"id":"cf8cafeea90ea3f2","repo":"sxyazi/yazi","slug":"entry-name-entry-must-be-in-kebab-case","errorCode":null,"errorMessage":"Entry name `{entry}` must be in kebab-case","messagePattern":"Entry name `(.+?)` must be in kebab-case","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"yazi-runner/src/loader/loader.rs","lineNumber":193,"sourceCode":"\tpub fn compatible_or_error(name: &str, chunk: &Chunk) -> Result<()> {\n\t\tif chunk.compatible() {\n\t\t\treturn Ok(());\n\t\t}\n\n\t\tbail!(\n\t\t\t\"Plugin `{name}` requires at least Yazi {}, but your current version is Yazi {}.\",\n\t\t\tchunk.since,\n\t\t\tyazi_version::version_long()\n\t\t);\n\t}\n\n\tfn explode_name_parts(name: &str) -> anyhow::Result<(&str, &str, &str)> {\n\t\tlet name = name.strip_suffix(\".main\").unwrap_or(name);\n\t\tlet (plugin, entry) =\n\t\t\tif let Some((a, b)) = name.split_once(\".\") { (a, b) } else { (name, \"main\") };\n\n\t\tensure!(plugin.as_bytes().kebab_cased(), \"Plugin name `{plugin}` must be in kebab-case\");\n\t\tensure!(entry.as_bytes().kebab_cased(), \"Entry name `{entry}` must be in kebab-case\");\n\t\tOk((name, plugin, entry))\n\t}\n}\n","sourceCodeStart":175,"sourceCodeEnd":197,"githubUrl":"https://github.com/sxyazi/yazi/blob/8ebf930f1796ae2076b7d6b0c5e93a1002c18134/yazi-runner/src/loader/loader.rs#L175-L197","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","solutions":["Rename the entry reference to kebab-case (e.g., `my-plugin.MySpot` -> `my-plugin.my-spot`)","Rename the entry Lua file inside the plugin directory to match kebab-case","Omit the entry suffix entirely if you mean the default `.main` entry"],"exampleFix":"// before\nya.plugin(\"my-plugin.MySpot\")\n// after\nya.plugin(\"my-plugin.my-spot\")","handlingStrategy":"validation","validationCode":"fn is_kebab(s: &str) -> bool {\n    !s.is_empty()\n        && s.bytes().all(|b| b.is_ascii_lowercase() || b.is_ascii_digit() || b == b'-')\n        && !s.starts_with('-') && !s.ends_with('-')\n}\nlet (plugin, entry) = name.split_once('.').unwrap_or((name, \"main\"));\nassert!(is_kebab(entry));","typeGuard":"fn valid_entry(name: &str) -> bool {\n    match name.split_once('.') {\n        Some((_, e)) => is_kebab(e),\n        None => true, // defaults to \"main\"\n    }\n}","tryCatchPattern":"match Loader::load(name) {\n    Ok(p) => p,\n    Err(e) => eprintln!(\"plugin load failed: {e}\") // message names the offending `entry`\n}","preventionTips":["Name entry files and references in lowercase kebab-case","Omit the entry suffix to use the default `.main` entry","Rename entry Lua files and all references together when refactoring"],"tags":["plugin","naming","validation","kebab-case"],"backgroundTag":"invalid-naming-convention","analyzedSha":"8ebf930f1796ae2076b7d6b0c5e93a1002c18134","analyzedAt":"2026-09-02T18:38:25.566Z","contentChangedAt":"2026-09-02T18:38:25.566Z","schemaVersion":2},"datasetVersion":"2026-09-14T00:17:10.932Z"}