jdx/mise · error

user service '{}' is also declared in [bootstrap.macos.launc

Error message

user service '{}' is also declared in [bootstrap.macos.launchd.agents]; declare it once

What it means

A user service name may not collide with a launchd agent declared in `[bootstrap.macos.launchd.agents]`. `requests_from_config` fails on the duplicate to avoid two managers fighting over the same service name.

Source

Thrown at src/system/user_services.rs:287

        .into_iter()
        .map(|(name, (declaration, origin))| {
            UserServiceRequest::from_toml(name, declaration, Some(origin))
        })
        .collect::<Result<Vec<_>>>()?;
    if requests.is_empty() {
        return Ok(requests);
    }
    let units = crate::system::systemd_from_config(config);
    let agents = crate::system::launchd_from_config(config);
    for request in &requests {
        if units.iter().any(|unit| unit.name == request.name) {
            bail!(
                "user service '{}' is also declared in [bootstrap.linux.systemd.units]; declare it once",
                request.name
            );
        }
        if agents.iter().any(|agent| agent.name == request.name) {
            bail!(
                "user service '{}' is also declared in [bootstrap.macos.launchd.agents]; declare it once",
                request.name
            );
        }
    }
    Ok(requests)
}

/// The mise executable a service definition may reference: the running
/// binary unless it lives in a temporary or remote-bootstrap staging
/// directory, else a `mise` on `PATH` outside those. Durability is judged
/// by where the binary really is, but the path kept is the one found: a
/// Homebrew or package-manager symlink survives an upgrade, the versioned
/// file behind it does not.
pub(crate) fn durable_mise_executable() -> Option<PathBuf> {
    let current = crate::env::MISE_BIN.clone();
    if durable_behind(&current) {
        return Some(current);

View on GitHub (pinned to afd2eddd3a)

Solutions

  1. Keep only one declaration: either the launchd agent or the user service
  2. Rename one if they are truly distinct services

Example fix

// before
[[bootstrap.macos.launchd.agents]]
name = "my-agent"
command = "my-agent"
[[bootstrap.macos.user_services]]
name = "my-agent"
command = "my-agent"

// after
[[bootstrap.macos.launchd.agents]]
name = "my-agent"
command = "my-agent"
Defensive patterns

Strategy: validation

Validate before calling

function validateNoLaunchdDupes(cfg) {
  const agentNames = new Set((cfg.bootstrap?.macos?.launchd?.agents ?? []).map(a => a.name));
  for (const s of cfg.bootstrap?.macos?.user_services ?? []) {
    if (agentNames.has(s.name)) throw new Error(`user service '${s.name}' duplicates a launchd agent`);
  }
}

Prevention

When it happens

Trigger: `requests_from_config` finds a user service request whose `name` matches a launchd agent name (src/system/user_services.rs:287).

Common situations: Sharing one config file across Linux and macOS and declaring the same service both as a launchd agent and a user service; leftover entries after switching service mechanisms.

Related errors


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