jdx/mise · error

expected a `run` command

Error message

expected a `run` command

What it means

In table form, a [bootstrap.hooks.<phase>] table must contain a run key; this error fires when the table exists but run is absent. Other keys that look equivalent (cmd, command, script) are not recognized, so a table using them is treated as having no run at all.

Source

Thrown at src/system/hooks.rs:90

        let Some(phase) = BootstrapHookPhase::parse(phase_raw) else {
            let valid = BootstrapHookPhase::iter()
                .map(|phase| phase.as_str())
                .collect::<Vec<_>>();
            bail!(
                "unknown bootstrap hook phase {phase_raw:?}; valid phases are: {}",
                valid.join(", ")
            );
        };
        let runs = match value {
            toml::Value::String(run) => vec![run],
            toml::Value::Array(values) => string_array(values, "expected string commands")?,
            toml::Value::Table(mut table) => match table.remove("run") {
                Some(toml::Value::String(run)) => vec![run],
                Some(toml::Value::Array(values)) => {
                    string_array(values, "expected `run` to contain string commands")?
                }
                Some(_) => bail!("expected `run` to be a string or array of strings"),
                None => bail!("expected a `run` command"),
            },
            _ => bail!("expected a string, array of strings, or table with `run`"),
        };
        let hooks = runs
            .into_iter()
            .filter_map(|run| {
                let run = run.trim().to_string();
                if run.is_empty() {
                    warn!("[bootstrap.hooks.{phase}]: empty command, ignoring entry");
                    None
                } else {
                    Some(Self { phase, run })
                }
            })
            .collect();
        Ok(hooks)
    }
}

View on GitHub (pinned to 9dcfcaa0dc)

Solutions

  1. Add run = "<command>" (or run = [ ... ]) to the phase table
  2. Rename unrecognized keys like cmd/command/script to run
  3. If the phase needs no command, delete the empty table

Example fix

# before
[bootstrap.hooks.final]
cmd = "./notify.sh"

# after
[bootstrap.hooks.final]
run = "./notify.sh"
Defensive patterns

Strategy: validation

Validate before calling

# every [bootstrap.hooks.<phase>] table must contain a run key
python3 - <<'EOF'
import tomllib,sys
c=tomllib.load(open('mise.toml','rb'))
for phase,v in (c.get('bootstrap',{}).get('hooks',{}) or {}).items():
    if isinstance(v,dict) and 'run' not in v: sys.exit(f'hook phase {phase} missing run')
EOF

Prevention

When it happens

Trigger: Writing [bootstrap.hooks.final] with cmd = "./notify.sh" instead of run, or an empty [bootstrap.hooks.final] table with no keys.

Common situations: Using key names carried over from other hook systems; starting a table intending to add the command later; typos or capitalized variants (Run, RUN) that TOML treats as different keys.

Related errors


AI-assisted analysis of jdx/mise@9dcfcaa0dc (2026-08-17). Data as JSON: /api/errors/a93174165402deaf. Report an issue: GitHub.