jdx/mise · error

expected a string, array of strings, or table with `run`

Error message

expected a string, array of strings, or table with `run`

What it means

Each value directly under [bootstrap.hooks] must be a string, an array of strings, or a table containing run. This error fires for any other TOML type at the top level of a phase entry — integer, float, or boolean — because none of those shapes can describe a command to run.

Source

Thrown at src/system/hooks.rs:92

                .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)
    }
}

fn string_array(values: Vec<toml::Value>, message: &str) -> Result<Vec<String>> {

View on GitHub (pinned to 9dcfcaa0dc)

Solutions

  1. Replace the scalar with a command string: final = "./finish.sh"
  2. Use an array for multiple commands: final = ["a.sh", "b.sh"]
  3. Remove the key entirely if no hook is wanted for that phase

Example fix

# before
[bootstrap.hooks]
final = true

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

Strategy: validation

Validate before calling

python3 - <<'EOF'
import tomllib,sys
c=tomllib.load(open('mise.toml','rb'))
for phase,v in (c.get('bootstrap',{}).get('hooks',{}) or {}).items():
    if not isinstance(v,(str,list,dict)): sys.exit(f'hook phase {phase} is {type(v).__name__}, need string/array/table')
EOF

Prevention

When it happens

Trigger: Writing [bootstrap.hooks] final = 3, final = 1.5, or final = false (enable/disable style) instead of a command value.

Common situations: Enable-flag style configs (final = true) copied from tools with toggles; numeric placeholders left in templated configs; YAML-to-TOML conversions that dropped the command string.

Related errors


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