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
- Set a non-blank command for the wrapper named in the error
- Delete the wrapper entry entirely if it is no longer needed (don't blank it to disable)
- 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
- Never blank out a wrapper's command to disable it — delete the entry
- Watch templated commands for variables that may resolve to empty strings
- Validate mise.toml with the JSON schema in your editor
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
- [daemons. ] requires preset when specifying version or…
- [daemons. ] requires run or preset
- expected a string, array of strings, or table with `run`
- agent ' ' `start_calendar_interval. ` must be between and
- agent ' ' `start_calendar_interval` must set at least one…
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)