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

Linux service {action} only manages the default zeroclaw ser

Error message

Linux service {action} only manages the default zeroclaw service. Config directory {config_dir} maps to named service {service}; provide that unit manually, then use service status/start/stop/restart/logs to manage it.

What it means

On Linux, install/uninstall only manage the default zeroclaw systemd unit. ensure_linux_default_install_scope derives the service name from the config directory; a non-default directory maps to a named service which the installer refuses to create, so it bails and tells you to provide that unit manually.

Source

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

    format!("{}.service", linux_service_base(config))
}

fn linux_openrc_service(config: &Config) -> String {
    linux_service_base(config)
}

fn ensure_linux_default_install_scope(config: &Config, action: &str) -> Result<()> {
    let service = linux_service_base(config);
    if service == "zeroclaw" {
        return Ok(());
    }

    let config_dir = config
        .config_path
        .parent()
        .map(|path| path.display().to_string())
        .unwrap_or_else(|| config.config_path.display().to_string());
    bail!(
        "Linux service {action} only manages the default zeroclaw service. \
         Config directory {config_dir} maps to named service {service}; \
         provide that unit manually, then use service status/start/stop/restart/logs to manage it."
    );
}

fn linux_systemd_action_args(config: &Config, action: &str) -> Vec<String> {
    vec![
        "--user".to_string(),
        action.to_string(),
        linux_systemd_unit(config),
    ]
}

fn linux_openrc_action_args(config: &Config, action: &str) -> Vec<String> {
    vec![linux_openrc_service(config), action.to_string()]
}

View on GitHub (pinned to 88bb9c8533)

Solutions

  1. Run install/uninstall with the default config directory (~/.config/zeroclaw) for the service-managed instance
  2. Or drop the named unit in yourself (zeroclaw@<name>.service template under ~/.config/systemd/user/) and manage it via 'zeroclaw service status/start/stop/restart/logs' with that config dir
  3. Reserve per-instance config dirs for manually provisioned units only

Example fix

# before
ZEROCLAW_CONFIG_DIR=~/.config/zeroclaw-second zeroclaw service install

# after: provide the named unit manually, then manage it
cp zeroclaw@.service ~/.config/systemd/user/
ZEROCLAW_CONFIG_DIR=~/.config/zeroclaw-second zeroclaw service start
Defensive patterns

Strategy: validation

Validate before calling

fn manages_default_scope_only(config: &Config) -> bool {
    let dir = config.config_path.parent().map(|p| p.to_path_buf());
    let home = std::env::var("HOME").unwrap_or_default();
    dir == Some(std::path::Path::new(&home).join(".config").join("zeroclaw"))
}

Prevention

When it happens

Trigger: Running 'zeroclaw service install' or 'zeroclaw service uninstall' on Linux while the config path (e.g. via ZEROCLAW_CONFIG_DIR or --config) lives in a non-default directory such as ~/.config/zeroclaw-second that maps to a named zeroclaw@<name> service.

Common situations: Running multiple zeroclaw instances from separate config dirs; automation that reuses one custom config path across hosts; CI pipelines setting a config dir before installing.

Related errors


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