jdx/mise · error

command wrapper for must have a non-blank command

Error message

command wrapper for {name:?} must have a non-blank command

What it means

load_command_wrappers found a [command-wrappers] (or alias) entry whose command string is blank (empty or whitespace). A wrapper must execute something, so configuration parsing fails with the offending wrapper's name in the message.

Solutions

  1. Set a non-blank command for the wrapper named in the error
  2. Delete the wrapper entry entirely if it is no longer needed (don't blank it to disable)
  3. Check templated command values for variables that resolve to empty strings

Example fix

// before
[command_wrappers.mytool]
command = ""
// after
[command_wrappers.mytool]
command = "mytool-wrapper"
Defensive patterns

Strategy: validation

Validate before calling

# check every wrapper command is non-blank before running mise
tomlq -r '.command_wrappers | to_entries[] | select(.value.command == "" or .value.command == null) | .key' mise.toml \
  && echo "blank wrapper commands found"

Type guard

// Rust
fn has_command(w: &CommandWrapper) -> bool {
    !w.command().trim().is_empty()
}

Try / catch

// Rust
match build_command_wrappers(&config_files, tools, safe_mode) {
    Ok(w) => use(w),
    Err(e) if e.to_string().contains("must have a non-blank command") => {
        eprintln!("fill in or delete the blank wrapper named in the error");
    }
    Err(e) => return Err(e),
}

Prevention

When it happens

Trigger: Collecting command wrappers from config files (command_wrappers()) where any wrapper's command(), after trim(), is empty — e.g. command = "" or command = " ". Safe mode only inspects global configs.

Common situations: Hand-editing mise.toml and leaving a wrapper's command blank, templating that resolves a command to an empty string, or disabling a wrapper by blanking it instead of deleting the entry.

Understand the failure class

Background: "must not be empty", "cannot be empty" — required-field validation errors across open-source libraries — this error's family across 41 libraries.

Related errors


AI-assisted analysis of jdx/mise@533346cc37 (2026-09-17). Data as JSON: /api/errors/3011e9554e4c5f36. Report an issue: GitHub.

Appendix: source

Thrown at src/config/mod.rs:3311

    trace!("load_shell_aliases: {}", shell_aliases.len());

    Ok(shell_aliases)
}

/// Load command wrappers from global through project scope.
pub(crate) fn load_command_wrappers<'a>(
    config_files: &ConfigMap,
    tools: impl IntoIterator<Item = &'a crate::toolset::ToolRequest>,
) -> Result<IndexMap<String, CommandWrapper>> {
    let mut wrappers = IndexMap::new();
    let safe_mode = Settings::safe_mode();
    for config_file in config_files.values().rev() {
        if safe_mode && !is_global_config(config_file.get_path()) {
            continue;
        }
        for (name, wrapper) in config_file.command_wrappers()? {
            if wrapper.command().trim().is_empty() {
                bail!("command wrapper for {name:?} must have a non-blank command");
            }
            wrappers.insert(name, wrapper);
        }
    }
    command_wrapper::add_rust_wrapper(&mut wrappers, tools)?;
    Ok(wrappers)
}

fn load_plugins(config_files: &ConfigMap) -> Result<HashMap<String, String>> {
    let mut plugins = HashMap::new();
    for config_file in config_files.values() {
        for (plugin, url) in config_file.plugins()? {
            plugins.insert(plugin.clone(), url.clone());
        }
    }
    trace!("load_plugins: {}", plugins.len());
    Ok(plugins)
}

View on GitHub (pinned to 533346cc37)