zeroclaw-labs/zeroclaw · error · anyhow::Error

Could not detect init system. Supported: systemd, OpenRC. Us

Error message

Could not detect init system. Supported: systemd, OpenRC. Use --service-init to specify manually.

What it means

On Linux, InitSystem::Auto.resolve() probes for systemd (runtime presence) and for OpenRC (/sbin/openrc-run on disk or rc-service in PATH). When neither is found the resolver gives up and asks the user to pass --service-init explicitly. This is an environment-detection failure, not a zeroclaw misconfiguration.

Source

Thrown at crates/zeroclaw-runtime/src/service/mod.rs:585

/// Detect the active init system on Linux
/// Checks for systemd and OpenRC in order, returning the first match.
/// Returns an error if neither is detected.
#[cfg(target_os = "linux")]
fn detect_init_system() -> Result<InitSystem> {
    // Check for systemd first (most common on modern Linux)
    if linux_systemd_runtime_present() {
        return Ok(InitSystem::Systemd);
    }

    // Check for OpenRC: requires /run/openrc AND openrc binary
    if Path::new("/run/openrc").exists() {
        // Check for OpenRC binaries: /sbin/openrc-run or rc-service in PATH
        if Path::new("/sbin/openrc-run").exists() || which::which("rc-service").is_ok() {
            return Ok(InitSystem::Openrc);
        }
    }

    bail!(
        "Could not detect init system. Supported: systemd, OpenRC. \
         Use --service-init to specify manually."
    );
}

pub(crate) fn linux_systemd_runtime_present() -> bool {
    cfg!(target_os = "linux") && Path::new("/run/systemd/system").exists()
}

fn windows_task_name() -> &'static str {
    WINDOWS_TASK_NAME
}

fn linux_service_base(config: &Config) -> String {
    let Some(dir_name) = config
        .config_path
        .parent()
        .and_then(Path::file_name)

View on GitHub (pinned to 88bb9c8533)

Solutions

  1. Pass the init system explicitly: zeroclaw service install --service-init systemd (or openrc)
  2. If a real service is required, install/enable systemd or OpenRC in that environment first
  3. In containers and CI, skip service management and run the daemon in the foreground

Example fix

# before
zeroclaw service install
# after
zeroclaw service install --service-init systemd
Defensive patterns

Strategy: fallback

Validate before calling

// replicate the runtime's detection before calling resolve()
fn detect_init() -> Option<InitSystem> {
    if std::path::Path::new("/run/systemd/system").exists() {
        return Some(InitSystem::Systemd);
    }
    if std::path::Path::new("/sbin/openrc-run").exists() || which::which("rc-service").is_ok() {
        return Some(InitSystem::Openrc);
    }
    None
}

Try / catch

let init = match InitSystem::Auto.resolve() {
    Ok(init) => init,
    Err(_) => InitSystem::Systemd, // explicit fallback instead of failing
};

Prevention

When it happens

Trigger: Calling install/start/stop/status/logs/uninstall with InitSystem::Auto on Linux where systemd is not running (no /run/systemd/system markers) and no OpenRC binaries exist: minimal Docker images, distroless CI runners, chroots, WSL1, devcontainers.

Common situations: Running 'zeroclaw service install' inside Docker/CI where PID 1 is not systemd; stripped-down VMs without an init system; build agents that only run the binary for smoke tests.

Related errors


AI-assisted analysis of zeroclaw-labs/zeroclaw@88bb9c8533 (2026-08-23). Data as JSON: /api/errors/3e7bd9059726f5ab. Report an issue: GitHub.