jdx/mise · error

`systemctl --user {}` failed: {}

Error message

`systemctl --user {}` failed: {}

What it means

This is the generic wrapper for failures of `systemctl --user <args>` invocations made by mise's systemd integration. When the systemctl child process exits non-zero, mise bails with the exact argument list and the trimmed stderr from systemctl, so the underlying systemd error is preserved in the message. A separate timeout variant exists if systemctl hangs.

Source

Thrown at src/system/systemd.rs:866

        );
    }
    Ok(false)
}

async fn systemctl(args: &[String]) -> Result<()> {
    debug!("$ systemctl --user {}", shell_words::join(args));
    let mut cmd = tokio::process::Command::new("systemctl");
    cmd.arg("--user")
        .args(args)
        .stdin(Stdio::null())
        .stdout(Stdio::piped())
        .stderr(Stdio::piped())
        .kill_on_drop(true);
    let output = tokio::time::timeout(SYSTEMCTL_TIMEOUT, cmd.output())
        .await
        .map_err(|_| eyre!("`systemctl --user {}` timed out", shell_words::join(args)))??;
    if !output.status.success() {
        bail!(
            "`systemctl --user {}` failed: {}",
            shell_words::join(args),
            String::from_utf8_lossy(&output.stderr).trim()
        );
    }
    Ok(())
}

async fn disable_unit(unit: &str) -> Result<()> {
    match systemctl(&["disable".to_string(), unit.to_string()]).await {
        Ok(()) => Ok(()),
        Err(err) if disable_unit_error_is_noop(&err.to_string()) => {
            debug!("systemd: ignoring disable for {unit}: {err}");
            Ok(())
        }
        Err(err) => Err(err),
    }
}

View on GitHub (pinned to afd2eddd3a)

Solutions

  1. Read the stderr portion of the message — it contains systemctl's actual reason — and fix the unit config accordingly.
  2. Run `systemctl --user status <unit>` and `journalctl --user -u <unit>` to inspect the failure.
  3. Ensure a user systemd session exists (`loginctl enable-linger $USER`; in SSH/containers verify `systemctl --user` works at all and DBUS_SESSION_BUS_ADDRESS/XDG_RUNTIME_DIR are set).
  4. Verify `exec_start` points to an existing, executable binary.
  5. Run `systemctl --user daemon-reload` after editing unit files.

Example fix

# message: `systemctl --user start myapp.service` failed: Failed to connect to bus: No such file or directory
# before: SSH session without lingering
loginctl enable-linger $USER
export XDG_RUNTIME_DIR=/run/user/$(id -u)
# after: systemctl --user can reach the user bus
Defensive patterns

Strategy: try-catch

Validate before calling

// preflight: is user systemd reachable at all?
const { execSync } = require('child_process');
function userSystemdReachable() {
  try { execSync('systemctl --user is-system-running', { stdio: 'ignore' }); return true; }
  catch (e) { return e.status !== 1 ? false : true; } // degraded still counts
}

Try / catch

// Rust caller
match run_systemctl(&["start", "myapp.service"]).await {
    Ok(()) => {}
    Err(e) => {
        eprintln!("systemctl failed: {e:#}");
        // inspect `journalctl --user -u myapp` and fix the unit before retrying
    }
}

Prevention

When it happens

Trigger: Any mise operation that shells out to `systemctl --user` (enable/start/daemon-reload/etc. for managed units) where systemctl exits non-zero — e.g. daemon-reload on a unit with a syntax error, starting a unit whose ExecStart binary is missing, or running without a user session/bus.

Common situations: Malformed generated unit files; missing executable referenced by `exec_start`; no user D-Bus/session in SSH or container contexts (`Failed to connect to bus`); `systemctl` not installed or systemd not running (e.g. WSL1, plain Docker without systemd); unit masked or dependency failed.

Related errors


AI-assisted analysis of jdx/mise@afd2eddd3a (2026-09-09). Data as JSON: /api/errors/b771d865f48fa021. Report an issue: GitHub.