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

journalctl exited with non-zero status

Error message

journalctl exited with non-zero status

What it means

For systemd installs, logs_linux builds journalctl arguments via linux_journalctl_args (unit filter, line count, follow) and runs journalctl. journalctl's non-zero exit is propagated verbatim; the underlying reason is only visible by running the same journalctl command by hand. Typical causes: no persistent journal for the user unit, permission on journal files, or the unit not existing yet.

Source

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

            .status()
            .context("Failed to run tail")?;
        if !status.success() {
            bail!("tail exited with non-zero status");
        }
    }
    Ok(())
}

fn logs_linux(config: &Config, init_system: InitSystem, lines: usize, follow: bool) -> Result<()> {
    match init_system {
        InitSystem::Systemd => {
            let args = linux_journalctl_args(config, lines, follow);
            let status = Command::new("journalctl")
                .args(&args)
                .status()
                .context("Failed to run journalctl")?;
            if !status.success() {
                bail!("journalctl exited with non-zero status");
            }
        }
        InitSystem::Openrc => {
            // OpenRC logs go to /var/log/<service>/error.log (as configured in the init script).
            let log_dir = linux_openrc_log_dir(config);
            let log_file = log_dir.join("error.log");
            if !log_file.exists() {
                // Fall back to access log
                let access_log = log_dir.join("access.log");
                if !access_log.exists() {
                    bail!(
                        "No log files found at {}. Is the service installed?",
                        log_dir.display()
                    );
                }
                return tail_file(&access_log, lines, follow);
            }
            tail_file(&log_file, lines, follow)?;

View on GitHub (pinned to 88bb9c8533)

Solutions

  1. Run the equivalent manually to see journalctl's own error: journalctl --user -u zeroclaw.service -n 50
  2. Enable persistent journal storage (Storage=persistent in /etc/systemd/journald.conf) and restart systemd-journald
  3. Enable lingering for the service user (loginctl enable-linger $USER) and add it to the systemd-journal group if needed

Example fix

# before
zeroclaw service logs
# after: surface the real journalctl failure
journalctl --user -u zeroclaw.service -n 50 --no-pager
Defensive patterns

Strategy: try-catch

Validate before calling

// cheap preflight: is there any persistent journal for user units?
if !std::path::Path::new("/var/log/journal").exists() {
    // journalctl will likely fail; enable persistent storage or read files directly
}

Try / catch

match service::logs(&config, InitSystem::Systemd, lines, follow) {
    Err(err) if err.to_string().contains("journalctl exited with non-zero status") => {
        // re-run the equivalent journalctl by hand to capture its stderr for diagnosis
        let _ = Command::new("journalctl").args(["--user", "-u", "zeroclaw.service", "-n", "50"]).status();
        return Err(err);
    }
    result => result?,
}

Prevention

When it happens

Trigger: 'zeroclaw service logs' with systemd on hosts where /var/log/journal is absent (volatile-only journal), inside containers, or when the zeroclaw user unit has never written a journal record.

Common situations: Minimal VMs/containers without persistent journald; user services without lingering enabled so logs land nowhere; journal files readable only by members of the systemd-journal group.

Related errors


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