{"record":{"id":"d195da84a0bd6b5a","repo":"sxyazi/yazi","slug":"command-name-cannot-be-empty","errorCode":null,"errorMessage":"command name cannot be empty","messagePattern":"command name cannot be empty","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"yazi-shared/src/event/cmd.rs","lineNumber":23,"sourceCode":"use mlua::{UserData, UserDataFields};\nuse serde_with::DeserializeFromStr;\nuse yazi_shim::{SStr, mlua::UserDataFieldsExt};\n\nuse crate::{data::{Data, DataKey}, sendable::Sendable};\n\n#[derive(Clone, Debug, Default, DeserializeFromStr)]\npub struct Cmd {\n\tpub name: SStr,\n\tpub args: HashMap<DataKey, Data>,\n}\n\nimpl FromStr for Cmd {\n\ttype Err = anyhow::Error;\n\n\tfn from_str(s: &str) -> Result<Self, Self::Err> {\n\t\tlet (mut words, last) = crate::shell::unix::split(s, true)?;\n\t\tif words.is_empty() || words[0].is_empty() {\n\t\t\tbail!(\"command name cannot be empty\");\n\t\t}\n\n\t\tOk(Self {\n\t\t\tname: mem::take(&mut words[0]).into(),\n\t\t\targs: Self::parse_args(words.into_iter().skip(1), last)?,\n\t\t})\n\t}\n}\n\nimpl Cmd {\n\tpub(crate) fn null() -> Self { Self { name: \"null\".into(), ..Default::default() } }\n\n\tpub fn parse_args<I>(words: I, last: Option<String>) -> Result<HashMap<DataKey, Data>>\n\twhere\n\t\tI: IntoIterator<Item = String>,\n\t{\n\t\tlet mut i = 0i64;\n\t\twords","sourceCodeStart":5,"sourceCodeEnd":41,"githubUrl":"https://github.com/sxyazi/yazi/blob/8ebf930f1796ae2076b7d6b0c5e93a1002c18134/yazi-shared/src/event/cmd.rs#L5-L41","documentation":"`Cmd::from_str` parses a command string by shell-splitting it (respecting quotes and an optional trailing `last` word). If the split yields no words, or the first word is empty (e.g. the string was empty or started with whitespace/quotes producing an empty name), it bails with \"command name cannot be empty\".","triggerScenarios":"Parsing an empty string with `\"\".parse::<Cmd>()`; parsing a string of only whitespace; a quoting quirk where `split` returns `\"\"` as words[0]; keymap/config entries whose command value is blank or unquoted-empty.","commonSituations":"Yazi keymap.toml / config where a `run` value is empty or only spaces; dynamically built command strings where a variable that should hold the command name is empty; plugins constructing Cmd from user input that was never validated.","solutions":["Validate the command string is non-empty and contains a real first token before parsing.","Fix the config/keymap entry so `run` (or equivalent) names a command, e.g. `run = 'arrow -1'`.","Trim whitespace before parsing and reject blank input at the boundary.","Check the shell split behavior if your command starts with quotes — ensure the command name is not quoted empty."],"exampleFix":"// before\nlet cmd: Cmd = user_input.parse()?; // user_input = \"\" or \"   \"\n// after\nlet s = user_input.trim();\nanyhow::ensure!(!s.is_empty(), \"command string is empty\");\nlet cmd: Cmd = s.parse()?;","handlingStrategy":"validation","validationCode":"fn valid_cmd(s: &str) -> bool {\n    let first = s.split_whitespace().next();\n    matches!(first, Some(w) if !w.is_empty())\n}","typeGuard":null,"tryCatchPattern":"let cmd: Cmd = user_input.trim().parse().map_err(|e| {\n    tracing::error!(\"bad command {user_input:?}: {e}\");\n    e\n})?;","preventionTips":["Trim and non-empty check command strings before parsing.","In keymap.toml, ensure every `run` value names a command.","Validate dynamic command builders: the first token must be a known command.","Avoid leading quotes/whitespace that can yield an empty first word."],"tags":["rust","parsing","command","yazi-shared"],"backgroundTag":"empty-command-name","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"}