jdx/mise · error

pitchfork

Error message

pitchfork {}: {}

What it means

The pitchfork runtime wrapper shells out to the pitchfork binary (status, supervisor, project list, usage, etc.) with a 15-second timeout and captures output. When pitchfork exits nonzero, mise surfaces the subcommand and pitchfork's stderr verbatim via this message. It is a passthrough wrapper error: the real cause is always in the appended stderr text.

Solutions

  1. Read the stderr appended to the message — it contains pitchfork's actual failure reason — and address that.
  2. Run the same command manually (e.g. `pitchfork status <id> --json`) from the project root to reproduce and see full output.
  3. If the supervisor is stale or dead, run `pitchfork supervisor restart` (or stop/start daemons) and retry.
  4. Validate the project's pitchfork.toml / mise daemon config for typos in daemon names.
Defensive patterns

Strategy: try-catch

Validate before calling

// Pre-check that pitchfork is invocable and the daemon id exists
try { JSON.parse(execSync('pitchfork status ' + id + ' --json', { cwd: root }).toString()); } catch { console.warn('daemon id unknown or pitchfork failing'); }

Type guard

function pitchforkOutputOk(out) {
  return typeof out === "string" && out.length > 0;
}

Try / catch

try {
  await mise.daemons.start();
} catch (e) {
  const m = String(e).match(/^pitchfork ([^:]+): (.*)$/s);
  if (m) console.error(`pitchfork subcommand '${m[1]}' failed: ${m[2]}`);
}

Prevention

When it happens

Trigger: Any call to Pitchfork::output where the spawned pitchfork command (args joined in the message) exits with a failing status — e.g. `pitchfork status <id> --json` for an unknown daemon, `pitchfork supervisor status --json` when no supervisor runs, or `pitchfork project list --json` failing; also raised if the 15s timeout produces an error propagated by the `??`.

Common situations: Querying a daemon id that pitchfork does not know, a stale/crashed pitchfork supervisor, pitchfork config errors (PITCHFORK_CONFIG is removed but the project's pitchfork.toml is invalid), or a hung pitchfork hitting the 15-second timeout.

Related errors


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

Appendix: source

Thrown at src/daemons/runtime.rs:123

        .ok_or_else(|| {
            eyre::eyre!(
                "daemons require pitchfork; run `mise use pitchfork` or `mise daemons start`"
            )
        })?;
        Ok(Self { bin, env })
    }

    pub(crate) async fn output(&self, root: &Path, args: &[String]) -> Result<String> {
        let mut command = Command::new(&self.bin);
        command
            .args(args)
            .envs(&self.env)
            .env_remove("PITCHFORK_CONFIG")
            .current_dir(root)
            .kill_on_drop(true);
        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"
            );

View on GitHub (pinned to 533346cc37)