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

tail exited with non-zero status

Error message

tail exited with non-zero status

What it means

In follow mode, logs_macos shells out to 'tail -n N -f <logfile>'. A non-zero tail exit is propagated as this error. Follow mode normally blocks until interrupted, so a non-zero exit usually means tail could not open or keep reading the file (deleted, rotated away, permission denied) or that tail is missing from PATH.

Source

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

    let log_file = if stderr_log.exists() {
        stderr_log
    } else if stdout_log.exists() {
        stdout_log
    } else {
        bail!(
            "No log files found in {}. Is the service installed?",
            logs_dir.display()
        );
    };

    if follow {
        let status = Command::new("tail")
            .args(["-n", &lines.to_string(), "-f"])
            .arg(&log_file)
            .status()
            .context("Failed to run tail")?;
        if !status.success() {
            bail!("tail exited with non-zero status");
        }
    } else {
        let status = Command::new("tail")
            .args(["-n", &lines.to_string()])
            .arg(&log_file)
            .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);

View on GitHub (pinned to 88bb9c8533)

Solutions

  1. Re-run 'zeroclaw service logs' after the file reappears
  2. Verify the file with ls -l on the plist's StandardErrorPath and fix ownership/permissions
  3. Reinstall the service so the log directory and files are recreated with correct modes
Defensive patterns

Strategy: try-catch

Validate before calling

// re-check immediately before following
if !log_file.exists() || log_file.metadata().map(|m| m.is_file()).unwrap_or(false) == false {
    // refresh: pick the newest *.log in the dir or tell the user to reinstall
}

Try / catch

match service::logs(&config, InitSystem::Auto, lines, true) {
    Err(err) if err.to_string().contains("tail exited with non-zero status") => {
        // likely rotation or permissions: report and retry once without follow
        let _ = service::logs(&config, InitSystem::Auto, lines, false);
    }
    result => result?,
}

Prevention

When it happens

Trigger: The log file is deleted or rotated between the existence check and tail startup; the file is unreadable to the current user; a stripped PATH inside the calling environment leaves 'tail' unresolved.

Common situations: Log rotation while following; permissions changed after install; running under a minimal environment (launchd agent, restricted shell) without coreutils in PATH.

Related errors


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