jdx/mise · error

pitchfork lacks external configuration support; upgrade to…

Error message

pitchfork lacks external configuration support; upgrade to pitchfork 2.25.0 or later

What it means

mise's daemon integration requires pitchfork's external `config` command support (pitchfork 2.25.0+) so mise can hand pitchfork a generated config. Before invoking it, mise probes `pitchfork usage` output and, if no `cmd config ` entry is listed, bails with this message instead of risking unknown-command fallback behavior. It means the installed pitchfork is too old for mise's daemon presets.

Solutions

  1. Upgrade pitchfork to 2.25.0 or later (e.g. `mise use pitchfork@latest` or `cargo install pitchfork`).
  2. Check the active version with `pitchfork --version` / `mise which pitchfork`; ensure no older binary shadows it on PATH.
  3. If upgrading is impossible, stop using mise daemon presets and manage daemons directly with pitchfork.

Example fix

// before
[tools]
pitchfork = "2.20.0"

// after
[tools]
pitchfork = "2.25.0"
Defensive patterns

Strategy: validation

Validate before calling

# Ensure pitchfork supports external config before enabling daemon presets
v=$(pitchfork --version); required=2.25.0
[ "$(printf '%s\n' "$required" "$v" | sort -V | head -1)" = "$required" ] || echo "upgrade pitchfork"

Try / catch

try {
  await mise.daemons.start();
} catch (e) {
  if (String(e).includes("lacks external configuration support")) {
    console.error("Upgrade pitchfork to >= 2.25.0.");
  }
}

Prevention

When it happens

Trigger: Calling supports_external_config during daemon prepare when `pitchfork usage` output contains no line starting with `cmd config ` or `cmd "config" ` — i.e. pitchfork < 2.25.0 is installed (or a fork/build without external config support).

Common situations: A pitchfork version installed via an old package manager, Homebrew, or cargo before 2.25.0 is on PATH while using `mise daemons` / daemon presets.

Understand the failure class

Background: "is deprecated and will be removed" — deprecation warnings for old API names, keywords, and options, and how to migrate before the removal release — this error's family across 29 libraries.

Related errors


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

Appendix: source

Thrown at src/daemons/runtime.rs:139

        let output = tokio::time::timeout(Duration::from_secs(15), command.output()).await??;
        if !output.status.success() {
            bail!(
                "pitchfork {}: {}",
                args.join(" "),
                String::from_utf8_lossy(&output.stderr)
            );
        }
        Ok(String::from_utf8(output.stdout)?)
    }

    pub(crate) async fn supports_external_config(&self, root: &Path) -> Result<()> {
        // Probe read-only usage metadata, never an unknown command (pitchfork's fallback starts daemons).
        let usage = self.output(root, &["usage".into()]).await?;
        if !usage.lines().any(|line| {
            line.trim_start().starts_with("cmd config ")
                || line.trim_start().starts_with("cmd \"config\" ")
        }) {
            bail!(
                "pitchfork lacks external configuration support; upgrade to pitchfork 2.25.0 or later"
            );
        }
        Ok(())
    }

    pub(crate) async fn status(&self, root: &Path, id: &str) -> Result<serde_json::Value> {
        let out = self
            .output(root, &["status".into(), id.into(), "--json".into()])
            .await?;
        Ok(serde_json::from_str(&out)?)
    }

    pub(crate) async fn supervisor_up(&self, root: &Path) -> Result<bool> {
        let out = self
            .output(
                root,
                &["supervisor".into(), "status".into(), "--json".into()],

View on GitHub (pinned to 533346cc37)