jdx/mise · error
task {} cache command input must not be empty: {command:?}
Error message
task {} cache command input must not be empty: {command:?} What it means
When computing/verifying a task's cache, mise re-derives command inputs from the task's cache.command_inputs entries. Each entry is treated as a command string; a blank or whitespace-only entry cannot produce a meaningful program/args pair, so mise fails the task naming the offending entry rather than silently ignoring it.
Source
Thrown at src/task/task_executor.rs:1423
sandbox.filter_env(resolved_env)
} else {
resolved_env.clone()
};
let timeout = task
.timeout
.as_ref()
.and_then(|value| match duration::parse_duration(value) {
Ok(timeout) => Some(timeout),
Err(err) => {
warn!("invalid timeout {:?} for task {}: {err}", value, task.name);
None
}
})
.unwrap_or(COMMAND_INPUT_TIMEOUT);
let mut inputs = Vec::with_capacity(cache.command_inputs.len());
for command in &cache.command_inputs {
if command.trim().is_empty() {
eyre::bail!(
"task {} cache command input must not be empty: {command:?}",
task.name
);
}
let (program, args, cmd_verbatim) =
self.get_cmd_program_and_args(command, task, &[])?;
// The same refusal as in `exec_program`, and it matters more here: these commands feed
// the cache key, so running them from C:\Windows would hash the wrong directory's
// answer. Measured on 2026.8.6 with the project on a UNC share — a `command_inputs`
// entry reading a file that exists in the project fails, while the same config on a
// local path succeeds. `--dry-run` does not reach here (see the cache branch in
// `run_task`), so there is nothing to exempt.
#[cfg(windows)]
if cmd_shell_cannot_use_dir(&program, &root) {
eyre::bail!("{}", unc_working_dir_error(&root));
}
#[cfg(not(windows))]
let _ = cmd_verbatim;View on GitHub (pinned to afd2eddd3a)
Solutions
- Remove the empty entry from cache.command_inputs in the task definition
- Fix the variable/template inside the entry that resolves to an empty string
- Filter blank strings at generation time if the list is built programmatically
- Re-run the task after cleaning the config
Example fix
# before [tasks.build.cache] command_inputs = ["", "Cargo.lock"] # after [tasks.build.cache] command_inputs = ["Cargo.lock"]
Defensive patterns
Strategy: validation
Validate before calling
const cmds = (config.cache?.command_inputs ?? []).map(c => c.trim());
const bad = cmds.findIndex(c => c === "");
if (bad !== -1) throw new Error(`command_inputs[${bad}] is empty`); Type guard
fn non_blank(s: &&str) -> bool { !s.trim().is_empty() }
// let valid: Vec<_> = command_inputs.iter().filter(non_blank).collect(); Try / catch
try {
await miseRun(["build"]);
} catch (e) {
if (String(e).includes("cache command input must not be empty")) {
console.error("Fix cache.command_inputs in mise.toml: remove blank entries");
}
throw e;
} Prevention
- Audit cache.command_inputs for blank entries after editing mise.toml
- Filter empty strings when building the list from variables/templates
- Use templates with defaults inside entries
- Lint task configs in CI before running
When it happens
Trigger: A task defines cache.command_inputs containing "", " ", or a tabs/newlines-only string; running the task (not under --dry-run) reaches task_executor.rs:1423 and bails on that entry.
Common situations: TOML like command_inputs = ["", "Cargo.lock"] from copy-paste; a template/variable that evaluates to an empty string inside an entry; a programmatically built list with an empty element.
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
- action prediction payload is too large
- task action manifest has an invalid identity
- task action manifest contains duplicate predictions
- remote action manifest keys must use blake3
- cached rustc output set is incomplete
AI-assisted analysis of jdx/mise@afd2eddd3a (2026-09-09).
Data as JSON: /api/errors/6fe6f35bf57793f2.
Report an issue: GitHub.