jdx/mise · error · eyre::Report
install_command cannot be used with filter_bins
Error message
install_command cannot be used with filter_bins
What it means
The spm backend treats `install_command` (full custom install) and `filter_bins` (post-build bin filtering) as mutually exclusive, because a custom command controls the whole install layout and filter_bins only makes sense against the default swift build output. source_install_command bails when both are set.
Source
Thrown at src/backend/spm.rs:154
fn install_command(&self) -> eyre::Result<Option<String>> {
let Some(value) = self.values.raw().opts.get("install_command") else {
return Ok(None);
};
let Some(command) = value.as_str() else {
bail!("install_command must be a non-empty string");
};
let command = command.trim();
if command.is_empty() {
bail!("install_command must be a non-empty string");
}
Ok(Some(command.to_string()))
}
fn source_install_command(&self) -> eyre::Result<Option<String>> {
let command = self.install_command()?;
if command.is_some() && self.filter_bins().is_some() {
bail!("install_command cannot be used with filter_bins");
}
Ok(command)
}
}
#[async_trait]
impl Backend for SPMBackend {
fn get_type(&self) -> BackendType {
BackendType::Spm
}
fn ba(&self) -> &Arc<BackendArg> {
&self.ba
}
fn get_dependencies(&self) -> eyre::Result<Vec<&str>> {
Ok(vec!["swift"])
}View on GitHub (pinned to 6f52dcdf99)
Solutions
- Remove `filter_bins` and let install_command fully own the output (it should place executables in the install path's bin/)
- Remove `install_command` and use the default swift build plus `filter_bins`
- If the command only renames binaries, drop it and use `bin = ...` / rename options instead
Example fix
# before [tools."spm:foo/bar"] version = "1.0.0" install_command = "make install PREFIX=$MISE_TOOL_INSTALL_PATH" filter_bins = "bar" # after [tools."spm:foo/bar"] version = "1.0.0" install_command = "make install PREFIX=$MISE_TOOL_INSTALL_PATH"
Defensive patterns
Strategy: validation
Validate before calling
entry=$(tomlq -r '.tools["spm:foo/bar"]' mise.toml 2>/dev/null); echo "$entry" | grep -q 'install_command' && echo "$entry" | grep -q 'filter_bins' && echo 'conflict: pick one'
Type guard
fn compatible_spm_opts(opts: &toml::Value) -> bool {
let m = opts.as_table().unwrap_or(&Default::default());
!(m.contains_key("install_command") && m.contains_key("filter_bins"))
} Prevention
- install_command owns the whole install; filter_bins owns post-build filtering — never both
- When adding options to an existing tool block, re-read which ones are mutually exclusive
When it happens
Trigger: A tool entry that sets both `install_command = "./install.sh"` and `filter_bins = "mybin"`. The conflict is checked whenever a custom install command is present.
Common situations: Incrementally adding filter_bins to an entry that already uses install_command, or copying options from two working examples into one tool block.
Related errors
- artifactbundle must be true, false, 1, or 0, got {value}
- install_command must be a non-empty string
- artifactbundle = false conflicts with spm.artifactbundle_onl
- artifactbundle_asset must end with .artifactbundle.zip, got
- No matching SwiftPM artifact bundle found for {}
AI-assisted analysis of jdx/mise@6f52dcdf99 (2026-08-22).
Data as JSON: /api/errors/242b217b7ea7ed5e.
Report an issue: GitHub.