{"record":{"id":"23875b2986243792","repo":"jdx/mise","slug":"conflicting-bootstrap-service-declarations-for-na-23875b","errorCode":null,"errorMessage":"conflicting bootstrap service declarations for {name}\n\n  first:\n    {}\n\n  second:\n    {}","messagePattern":"conflicting bootstrap service declarations for (.+?)\n\n  first:\n    (.+?)\n\n  second:\n    (.+?)","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"src/system/services_non_linux.rs","lineNumber":85,"sourceCode":"    fn notify(&mut self, source: ResourceId, services: &[String]) {\n        for service in services {\n            self.sources\n                .entry(service.clone())\n                .or_default()\n                .insert(source.clone());\n        }\n    }\n}\n\npub(crate) fn prepare_requests_from_config(config: &Config) -> Result<Vec<ServiceRequest>> {\n    let mut composed: IndexMap<String, (ServiceTomlConfig, ResourceOrigin)> = IndexMap::new();\n    for config_files in config.bootstrap_config_maps() {\n        for (name, declaration) in services_from_config_files(config_files) {\n            if let Some(existing) = composed.get(&name) {\n                if existing.0 == declaration.0 {\n                    continue;\n                }\n                bail!(\n                    \"conflicting bootstrap service declarations for {name}\\n\\n  first:\\n    {}\\n\\n  second:\\n    {}\",\n                    existing.1.conflict_description(),\n                    declaration.1.conflict_description(),\n                );\n            }\n            composed.insert(name, declaration);\n        }\n    }\n    Ok(composed\n        .into_iter()\n        .map(|(name, _)| ServiceRequest { name })\n        .collect())\n}\n\nfn services_from_config_files(\n    config_files: &ConfigMap,\n) -> IndexMap<String, (ServiceTomlConfig, ResourceOrigin)> {\n    let mut merged = IndexMap::new();","sourceCodeStart":67,"sourceCodeEnd":103,"githubUrl":"https://github.com/jdx/mise/blob/6f52dcdf99e282ef7a7db68c81301fa4618d0f79/src/system/services_non_linux.rs#L67-L103","documentation":"When composing bootstrap service declarations across config layers (project, local, global and other `bootstrap_config_maps` sources), mise allows the same service name only if every declaration is byte-identical. Two declarations of the same name that differ in any field abort config loading, with the origin of each shown in the message.","triggerScenarios":"Two mise config files that both load (e.g. `~/.config/mise/config.toml` and the project `mise.toml`, or a local override) each define `[bootstrap.services.<name>]` with different values for state/enabled/masked/on_change.","commonSituations":"Team-wide global config sets a service and a developer overrides it locally with different settings instead of removing one; copied config files drift apart; a renamed field on one side makes previously-identical blocks differ.","solutions":["Pick one source of truth: delete the service block from one of the two files named in the error","Or make both declarations exactly identical (all fields equal) so composition skips the duplicate","Use `mise bootstrap plan` / config origin output to confirm which files contributed before and after cleanup","Split differing intents into two differently-named services if both are genuinely wanted"],"exampleFix":"# before\n# ~/.config/mise/config.toml\n[bootstrap.services.caddy]\nstate = \"running\"\non_change = \"restart\"\n\n# ./mise.toml (project)\n[bootstrap.services.caddy]\nstate = \"stopped\"\n\n# after: keep it only in the project file, delete the global block","handlingStrategy":"validation","validationCode":"mise bootstrap plan 2>&1 >/dev/null | grep -A4 'conflicting bootstrap service' || true\n# also: search every loaded config for duplicate service tables\nfor f in mise.toml mise.local.toml ~/.config/mise/config.toml; do [ -f \"$f\" ] && grep -n '^\\[bootstrap.services\\.' \"$f\"; done | sort | uniq -d","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Keep each service declared in exactly one config layer; use includes instead of re-declaring","When overriding, delete the other layer's block rather than editing values piecemeal","Use the conflict message's two `conflict_description` origins to find both files fast"],"tags":["mise","bootstrap","config","conflict","multiple-sources"],"backgroundTag":"config-conflict-duplicate-key","analyzedSha":"6f52dcdf99e282ef7a7db68c81301fa4618d0f79","analyzedAt":"2026-08-22T10:14:23.840Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}