jdx/mise · error

[daemons. ] requires run or preset

Error message

[daemons.{name}] requires run or preset

What it means

Every daemon declaration must either reference a `preset` or provide a `run` command string. If a `[daemons.<name>]` table has neither a preset (checked earlier) nor a string-valued `run` key, mise cannot know what to start and bails during load.

Solutions

  1. Add `run = "<command>"` to the daemon table.
  2. Add `preset = "<name>"` if you want a predefined daemon template.
  3. Verify `run` is a quoted TOML string, not an array or table.

Example fix

# before
[daemons.web]
port = 3000

# after
[daemons.web]
run = "npm run dev"
port = 3000
Defensive patterns

Strategy: validation

Validate before calling

# shell: each daemons block must have run or preset
awk '/^\[daemons\./{name=$0; has=0} /^(run|preset) /= {has=1} /^\[/{if (name && !has) print "missing run/preset: " name}' mise.toml

Prevention

When it happens

Trigger: Declaring `[daemons.foo]` with no `run` and no `preset`, or with a `run` key whose value is not a TOML string (e.g. an array or integer) — `toml::Value::as_str()` returns None and the check fails.

Common situations: Empty daemon stubs left in config; `run` defined with wrong TOML type (unquoted or as a table); config edited to remove the command but keep the daemon block.

Understand the failure class

Background: "is required", "must be set", "missing required field": configuration validation errors across open-source libraries — this error's family across 36 libraries.

Related errors


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

Appendix: source

Thrown at src/daemons/mod.rs:101

        }
        let (preset, version, mut table) = match declaration {
            Declaration::Preset(version) => (Some(name.clone()), Some(version), toml::Table::new()),
            Declaration::Definition(mut table) => {
                let preset = take_string(&mut table, "preset")?;
                let version = take_string(&mut table, "version")?;
                (preset, version, table)
            }
        };
        let daemon = if let Some(preset) = preset {
            let version = version
                .ok_or_else(|| eyre::eyre!("[daemons.{name}] requires version with preset"))?;
            presets::expand(&name, &preset, &version, table, &source, &root)?
        } else {
            if version.is_some() || table.contains_key("options") {
                bail!("[daemons.{name}] requires preset when specifying version or options");
            }
            if table.get("run").and_then(toml::Value::as_str).is_none() {
                bail!("[daemons.{name}] requires run or preset");
            }
            if let Some(port) = table.get("port").and_then(toml::Value::as_integer) {
                if !(1..=65535).contains(&port) {
                    bail!("daemon port must be an integer from 1 to 65535");
                }
                table.insert(
                    "port".into(),
                    toml::Value::Table(toml::Table::from_iter([
                        (
                            "expect".into(),
                            toml::Value::Array(vec![toml::Value::Integer(port)]),
                        ),
                        ("bump".into(), toml::Value::Boolean(false)),
                    ])),
                );
            }
            table
                .entry("mise".to_string())

View on GitHub (pinned to 533346cc37)