{"record":{"id":"9f4c8eb925c5722e","repo":"jdx/mise","slug":"pitchfork","errorCode":null,"errorMessage":"pitchfork {}: {}","messagePattern":"pitchfork (.+?): (.+?)","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"src/daemons/runtime.rs","lineNumber":123,"sourceCode":"        .ok_or_else(|| {\n            eyre::eyre!(\n                \"daemons require pitchfork; run `mise use pitchfork` or `mise daemons start`\"\n            )\n        })?;\n        Ok(Self { bin, env })\n    }\n\n    pub(crate) async fn output(&self, root: &Path, args: &[String]) -> Result<String> {\n        let mut command = Command::new(&self.bin);\n        command\n            .args(args)\n            .envs(&self.env)\n            .env_remove(\"PITCHFORK_CONFIG\")\n            .current_dir(root)\n            .kill_on_drop(true);\n        let output = tokio::time::timeout(Duration::from_secs(15), command.output()).await??;\n        if !output.status.success() {\n            bail!(\n                \"pitchfork {}: {}\",\n                args.join(\" \"),\n                String::from_utf8_lossy(&output.stderr)\n            );\n        }\n        Ok(String::from_utf8(output.stdout)?)\n    }\n\n    pub(crate) async fn supports_external_config(&self, root: &Path) -> Result<()> {\n        // Probe read-only usage metadata, never an unknown command (pitchfork's fallback starts daemons).\n        let usage = self.output(root, &[\"usage\".into()]).await?;\n        if !usage.lines().any(|line| {\n            line.trim_start().starts_with(\"cmd config \")\n                || line.trim_start().starts_with(\"cmd \\\"config\\\" \")\n        }) {\n            bail!(\n                \"pitchfork lacks external configuration support; upgrade to pitchfork 2.25.0 or later\"\n            );","sourceCodeStart":105,"sourceCodeEnd":141,"githubUrl":"https://github.com/jdx/mise/blob/533346cc374382b41ec5ff70536252b2e96e725c/src/daemons/runtime.rs#L105-L141","documentation":"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.","triggerScenarios":"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 `??`.","commonSituations":"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.","solutions":["Read the stderr appended to the message — it contains pitchfork's actual failure reason — and address that.","Run the same command manually (e.g. `pitchfork status <id> --json`) from the project root to reproduce and see full output.","If the supervisor is stale or dead, run `pitchfork supervisor restart` (or stop/start daemons) and retry.","Validate the project's pitchfork.toml / mise daemon config for typos in daemon names."],"exampleFix":null,"handlingStrategy":"try-catch","validationCode":"// Pre-check that pitchfork is invocable and the daemon id exists\ntry { JSON.parse(execSync('pitchfork status ' + id + ' --json', { cwd: root }).toString()); } catch { console.warn('daemon id unknown or pitchfork failing'); }","typeGuard":"function pitchforkOutputOk(out) {\n  return typeof out === \"string\" && out.length > 0;\n}","tryCatchPattern":"try {\n  await mise.daemons.start();\n} catch (e) {\n  const m = String(e).match(/^pitchfork ([^:]+): (.*)$/s);\n  if (m) console.error(`pitchfork subcommand '${m[1]}' failed: ${m[2]}`);\n}","preventionTips":["Read the stderr appended to the message first — it names the real cause","Keep the project's pitchfork.toml valid and daemon names consistent with mise.toml","Restart a stale supervisor with `pitchfork supervisor restart` before retrying"],"tags":["pitchfork","subprocess","cli"],"backgroundTag":"command-not-found","analyzedSha":"533346cc374382b41ec5ff70536252b2e96e725c","analyzedAt":"2026-09-17T13:35:38.149Z","contentChangedAt":"2026-09-17T13:35:38.149Z","schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}