{"record":{"id":"67dd16868fb180a7","repo":"jdx/mise","slug":"tool-option-requires-a-non-empty-key","errorCode":null,"errorMessage":"--tool-option requires a non-empty key","messagePattern":"--tool-option requires a non-empty key","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"src/cli/use.rs","lineNumber":199,"sourceCode":"    }\n\n    fn request_options(&self) -> Result<ToolVersionOptions> {\n        let mut options = ToolVersionOptions::default();\n        let mut entries = Vec::new();\n        if let Some(command) = &self.postinstall {\n            entries.push((\n                \"postinstall\".to_string(),\n                toml::Value::String(command.clone()),\n                \"--postinstall\",\n            ));\n        }\n        for option in &self.tool_option {\n            let (key, value) = option\n                .split_once('=')\n                .ok_or_else(|| eyre!(\"--tool-option expects KEY=VALUE: {option}\"))?;\n            let key = key.trim();\n            if key.is_empty() {\n                bail!(\"--tool-option requires a non-empty key\");\n            }\n            let value = toml::from_str::<toml::Table>(&format!(\"value = {value}\"))\n                .ok()\n                .filter(|table| table.len() == 1)\n                .and_then(|mut table| table.remove(\"value\"))\n                .unwrap_or_else(|| toml::Value::String(value.to_string()));\n            entries.push((key.to_string(), value, \"--tool-option\"));\n        }\n        let mut seen = std::collections::HashSet::new();\n        for (key, value, flag) in entries {\n            if !seen.insert(key.clone()) {\n                bail!(\n                    \"tool option {key:?} was specified more than once for {}\",\n                    self.tool\n                );\n            }\n            if self\n                .tool","sourceCodeStart":181,"sourceCodeEnd":217,"githubUrl":"https://github.com/jdx/mise/blob/afd2eddd3a50c16190efc1c7e94404b48f72af57/src/cli/use.rs#L181-L217","documentation":"`mise use --tool-option` expects each option in KEY=VALUE form with a non-empty key; request_options() rejects options whose key is empty after trimming. This guards the tool-options TOML map from empty keys.","triggerScenarios":"Passing `--tool-option '=value'` or `--tool-option ' =value'` (key empty before/after trim) to `mise use`, in request_options().","commonSituations":"Shell quoting mishaps leaving an empty key; scripting loops that build --tool-option strings from empty variable names; copy-paste errors.","solutions":["Provide a non-empty key: `--tool-option key=value`.","Check the variable that supplies the key in scripts.","Quote the argument properly in shell to avoid splitting."],"exampleFix":"// before\nmise use --tool-option '=true' node\n// after\nmise use --tool-option 'version=true' node","handlingStrategy":"validation","validationCode":"case \"$opt\" in *=*) key=\"${opt%%=*}\"; [ -n \"${key//[[:space:]]/}\" ] || exit 1 ;; *) exit 1 ;; esac","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Always emit --tool-option as KEY=VALUE with a non-empty key.","Validate option strings generated by scripts before passing them.","Quote arguments to prevent shell splitting artifacts."],"tags":["cli","tool-options","argument-validation"],"backgroundTag":"empty-required-field","analyzedSha":"afd2eddd3a50c16190efc1c7e94404b48f72af57","analyzedAt":"2026-09-09T01:38:25.179Z","contentChangedAt":"2026-09-09T01:38:25.179Z","schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}