zeroclaw-labs/zeroclaw · error · anyhow::Error
the launchd daemon runner is only supported on macOS
Error message
the launchd daemon runner is only supported on macOS
What it means
run_launchd_daemon is compiled as a stub on non-macOS targets that always bails (service/mod.rs:333-338). The launchd daemon runner captures launchd-managed stdout/stderr paths, so calling it on Linux or Windows can never succeed.
Source
Thrown at crates/zeroclaw-runtime/src/service/mod.rs:336
{
let mut buffer = vec![0; 16 * 1024];
loop {
match pipe.read(&mut buffer).await {
Ok(0) => break,
Ok(read) => sink.push(buffer[..read].to_vec()),
Err(error) => {
sink.push(format!("launchd log pipe read failed: {error}\n").into_bytes());
break;
}
}
}
}
pub async fn run_launchd_daemon(config_dir: &Path) -> Result<()> {
#[cfg(not(target_os = "macos"))]
{
let _ = config_dir;
bail!("the launchd daemon runner is only supported on macOS")
}
#[cfg(target_os = "macos")]
{
let paths = launchd_capture_paths(config_dir);
run_with_launchd_capture(paths, || {
let executable = std::env::current_exe()
.context("Failed to resolve the launchd daemon executable")?;
let mut command = TokioCommand::new(executable);
command.arg("--config-dir").arg(config_dir).arg("daemon");
Ok(command)
})
.await
}
}
#[cfg(any(target_os = "macos", test))]
async fn run_with_launchd_capture<F>(paths: LaunchdCapturePaths, make_command: F) -> Result<()>View on GitHub (pinned to 88bb9c8533)
Solutions
- Gate the call: invoke run_launchd_daemon only when std::env::consts::OS == "macos" (or via #[cfg(target_os = "macos")])
- On Linux use the OpenRC runner (run_openrc_log_writer) or the platform-appropriate service path
- Derive the runner choice from the detected OS in your dispatcher
Example fix
// before
run_launchd_daemon(config_dir).await?;
// after
#[cfg(target_os = "macos")]
run_launchd_daemon(config_dir).await?;
#[cfg(not(target_os = "macos"))]
anyhow::bail!("launchd runner requires macOS; this build targets {}", std::env::consts::OS); Defensive patterns
Strategy: validation
Validate before calling
fn is_macos() -> bool {
std::env::consts::OS == "macos"
}
if is_macos() {
run_launchd_daemon(config_dir).await?;
} else {
tracing::warn!(os = std::env::consts::OS, "skipping launchd daemon: macOS only");
} Type guard
fn supports_launchd() -> bool { cfg!(target_os = "macos") } Try / catch
If the call still fails, treat 'only supported on macOS' as a dispatcher bug: log the detected OS and route to the OpenRC or platform runner; never retry the launchd path on a non-macOS host.
Prevention
- Select daemon runners from runtime OS detection
- Keep per-OS CI coverage for service commands
- Refuse to install macOS service definitions on non-macOS hosts
When it happens
Trigger: Invoking the launchd daemon entry point on a Linux or Windows build — e.g. a service dispatcher keyed by config instead of OS, or a Linux CI host running macOS-targeted service commands.
Common situations: A macos-style service config deployed to a Linux box; cross-platform binary with a single hardcoded runner; CI matrix running the launchd path on the wrong OS job.
Related errors
- the OpenRC log writer is only supported on Linux
- daemon child exited with status {status}
- launchctl start failed: {}
- Service management is supported on macOS and Linux only
- Service log viewing is supported on macOS, Linux, and Window
AI-assisted analysis of zeroclaw-labs/zeroclaw@88bb9c8533 (2026-08-23).
Data as JSON: /api/errors/bb75f40920f6f3a1.
Report an issue: GitHub.