jdx/mise · error
conflicting bootstrap service declarations for {name}\n\n f
Error message
conflicting bootstrap service declarations for {name}\n\n first:\n {}\n\n second:\n {} What it means
Service declarations are collected from every bootstrap config layer (prepare_requests_from_config, src/system/services.rs:150). When two layers declare the same service name, identical declarations are merged silently — but if the TOML bodies differ, bootstrap bails, printing the origin (file/section) of both the first and second declaration so you can see exactly which files fight.
Source
Thrown at src/system/services.rs:150
dependency_changed: bool,
notified: bool,
active: bool,
}
#[derive(Clone, Debug, Default, Serialize, Deserialize)]
struct ServicePlan {
actions: Vec<ServiceAction>,
}
pub(crate) fn prepare_requests_from_config(config: &Config) -> Result<Vec<ServiceRequest>> {
let mut composed: IndexMap<String, (ServiceTomlConfig, ResourceOrigin)> = IndexMap::new();
for config_files in config.bootstrap_config_maps() {
for (name, declaration) in services_from_config_files(config_files) {
if let Some(existing) = composed.get(&name) {
if existing.0 == declaration.0 {
continue;
}
bail!(
"conflicting bootstrap service declarations for {name}\n\n first:\n {}\n\n second:\n {}",
existing.1.conflict_description(),
declaration.1.conflict_description(),
);
}
composed.insert(name, declaration);
}
}
composed
.into_iter()
.map(|(name, (config, origin))| {
ServiceRequest::from_toml_with_origin(name, config, Some(origin))
})
.collect()
}
fn services_from_config_files(
config_files: &ConfigMap,View on GitHub (pinned to 6f52dcdf99)
Solutions
- Open both files named in the 'first:'/'second:' blocks of the message and diff the two service declarations
- Make them byte-identical (then the duplicate is harmless and merged), or
- Delete the declaration from the layer that should not own it — one owner per service
- Re-run bootstrap; collection succeeds once names no longer collide with differing bodies
Example fix
# before: ./mise.toml has [bootstrap.services.nginx] state = "running" # ~/.config/mise/config.toml has [bootstrap.services.nginx] state = "stopped" # -> bail with both origins # after: keep it only in ./mise.toml (delete the user-level block)
Defensive patterns
Strategy: validation
Validate before calling
# diff service declarations across config layers before bootstrap runs
python3 - <<'PY'
import tomllib, glob, os, collections
seen = {}
files = ['mise.toml'] + glob.glob(os.path.expanduser('~/.config/mise/*.toml'))
for f in files:
svc = tomllib.load(open(f,'rb')).get('bootstrap',{}).get('services',{})
if not isinstance(svc, dict): continue
for name, body in svc.items():
if name in seen and seen[name] != body:
print(f"conflicting declarations for service {name}: {seen[name]['_file']} vs {f}")
body = dict(body); body['_file'] = f
seen.setdefault(name, body)
PY Prevention
- One owner per service: declare each service in a single config layer
- When overriding is needed, re-declare the service identically in the more specific layer (identical bodies merge silently)
- Remove stale parent-directory configs after moving a project
When it happens
Trigger: The same service name declared in two config files (project mise.toml plus user/global config, or multiple included files) with any difference in state, enabled, masked, or on_change fields. The conflict_description() values in the message identify both origins.
Common situations: Overriding a machine-wide service setting per-project instead of fully re-declaring it identically; an old config copy left in a parent directory; teams share a base config and a developer tweaked one copy.
Related errors
- bootstrap service '{name}' cannot be both masked and running
- bootstrap service '{name}' cannot be both masked and enabled
- refusing unsafe change to bootstrap service '{}'; inspect `m
- refusing unsafe change to bootstrap service '{}'; current st
- systemctl {} failed: {}
AI-assisted analysis of jdx/mise@6f52dcdf99 (2026-08-22).
Data as JSON: /api/errors/ced3fb3512c2c9a7.
Report an issue: GitHub.