jdx/mise · error

install_command `{install_command}` exited successfully but

Error message

install_command `{install_command}` exited successfully but installed no executable into {}; check that it installs into $MISE_TOOL_INSTALL_PATH and that it fails when the build fails

What it means

After running a custom install_command, mise sanity-checks the target bin directory ($MISE_TOOL_INSTALL_PATH/bin): it must contain at least one executable file. A command that exits 0 but produces nothing (or nothing executable) is treated as a broken install, since most build tools fail loudly on error and silence here usually means the command didn't actually install anything.

Source

Thrown at src/backend/spm.rs:707

    }
    Ok(executables
        .into_iter()
        .filter(|e| filter.contains(e))
        .collect())
}

/// Verifies that `install_command` actually installed an executable into `bin/`.
///
/// A package's install script may exit 0 even when the underlying `swift build`
/// failed (for example when the script does not use `set -e`), which would
/// otherwise leave mise reporting a successful install for a directory that has
/// no runnable tool in it.
fn verify_install_command_output(install_command: &str, bin_path: &Path) -> eyre::Result<()> {
    if !file::ls(bin_path)?
        .iter()
        .any(|entry| entry.is_file() && file::is_executable(entry))
    {
        bail!(
            "install_command `{install_command}` exited successfully but installed no executable into {}; check that it installs into $MISE_TOOL_INSTALL_PATH and that it fails when the build fails",
            bin_path.display()
        );
    }
    Ok(())
}

#[derive(Clone, Debug, Eq, PartialEq)]
pub(crate) struct GitProvider {
    pub api_url: String,
    pub kind: GitProviderKind,
}

impl Default for GitProvider {
    fn default() -> Self {
        Self {
            api_url: github::API_URL.to_string(),
            kind: GitProviderKind::GitHub,

View on GitHub (pinned to afd2eddd3a)

Solutions

  1. Make the install_command copy the built executable into $MISE_TOOL_INSTALL_PATH/bin and chmod +x it
  2. Verify the build output path (e.g. .build/release/<tool>) and adjust the copy command
  3. Test the command manually with MISE_TOOL_INSTALL_PATH set to a temp dir to confirm it populates bin/

Example fix

// before
install_command = "swift build -c release"

// after
install_command = "swift build -c release && install -m 0755 .build/release/mytool "$MISE_TOOL_INSTALL_PATH/bin/""
Defensive patterns

Strategy: validation

Validate before calling

# Dry-run the install command locally
export MISE_TOOL_INSTALL_PATH=/tmp/spmtest
rm -rf $MISE_TOOL_INSTALL_PATH && mkdir -p $MISE_TOOL_INSTALL_PATH/bin
sh -c "$INSTALL_COMMAND" && ls -l $MISE_TOOL_INSTALL_PATH/bin  # must show an executable

Prevention

When it happens

Trigger: install_command script that builds but never copies the binary into $MISE_TOOL_INSTALL_PATH, copies to the wrong directory, or copies a non-executable file; called from run_install_command during install.

Common situations: Using `swift build` alone without a copy step, wrong output path (.build/release vs $MISE_TOOL_INSTALL_PATH), or forgetting chmod +x on the copied binary.

Understand the failure class

Background: "Invalid value" and "allowed values are" config errors: what your library rejected and how to fix it — this error's family across 41 libraries.

Related errors


AI-assisted analysis of jdx/mise@afd2eddd3a (2026-09-09). Data as JSON: /api/errors/2bbc6de45b8c4003. Report an issue: GitHub.