{"record":{"id":"9fa25c153acf9bb4","repo":"jdx/mise","slug":"install-command-must-be-a-non-empty-string","errorCode":null,"errorMessage":"install_command must be a non-empty string","messagePattern":"install_command must be a non-empty string","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"src/backend/spm.rs","lineNumber":142,"sourceCode":"                .filter_map(|v| v.as_str().map(|s| s.trim().to_string()))\n                .filter(|s| !s.is_empty())\n                .collect(),\n            toml::Value::String(s) => s\n                .split(',')\n                .map(|s| s.trim().to_string())\n                .filter(|s| !s.is_empty())\n                .collect(),\n            _ => return None,\n        };\n        if bins.is_empty() { None } else { Some(bins) }\n    }\n\n    fn install_command(&self) -> eyre::Result<Option<String>> {\n        let Some(value) = self.values.raw().opts.get(\"install_command\") else {\n            return Ok(None);\n        };\n        let Some(command) = value.as_str() else {\n            bail!(\"install_command must be a non-empty string\");\n        };\n        let command = command.trim();\n        if command.is_empty() {\n            bail!(\"install_command must be a non-empty string\");\n        }\n        Ok(Some(command.to_string()))\n    }\n\n    fn source_install_command(&self) -> eyre::Result<Option<String>> {\n        let command = self.install_command()?;\n        if command.is_some() && self.filter_bins().is_some() {\n            bail!(\"install_command cannot be used with filter_bins\");\n        }\n        Ok(command)\n    }\n}\n\n#[async_trait]","sourceCodeStart":124,"sourceCodeEnd":160,"githubUrl":"https://github.com/jdx/mise/blob/533346cc374382b41ec5ff70536252b2e96e725c/src/backend/spm.rs#L124-L160","documentation":"The SPM backend's optional 'install_command' option must be a string. If the option is present but is not a string (e.g. an array, boolean, or table), the backend cannot build a shell command and throws this error. Despite the message, this variant is specifically the wrong-type case.","triggerScenarios":"Defining install_command as a non-string TOML value (array, inline table, boolean) in an spm tool's options; the option is read in install_command() invoked via source_install_command.","commonSituations":"Trying to express a multi-command install as a TOML array; accidental TOML structure mistakes; copying config from a different tool backend with different option types.","solutions":["Provide install_command as a single non-empty string containing the full command","Join multiple commands into one string (e.g. with &&) instead of an array","Remove the option to fall back to the default source build"],"exampleFix":"# before\ninstall_command = [\"swift\", \"build\"]\n# after\ninstall_command = \"swift build -c release\"","handlingStrategy":"type-guard","validationCode":"# ensure install_command is a string in TOML\n# valid: install_command = \"swift build\"\n# invalid: install_command = [\"swift\", \"build\"]","typeGuard":"fn is_nonempty_string(v: &toml::Value) -> bool {\n    v.as_str().map(|s| !s.trim().is_empty()).unwrap_or(false)\n}","tryCatchPattern":null,"preventionTips":["Express multi-step installs as one &&-joined string","Don't copy option types from other backends","Check TOML types with a linter/schema validator"],"tags":["spm","swift","config","type-mismatch"],"backgroundTag":"config-type-mismatch","analyzedSha":"533346cc374382b41ec5ff70536252b2e96e725c","analyzedAt":"2026-09-17T13:35:38.149Z","contentChangedAt":"2026-09-17T13:35:38.149Z","schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}