{"record":{"id":"4f124b267256cd9f","repo":"jdx/mise","slug":"bootstrap-service-name-cannot-be-both-masked-a-4f124b","errorCode":null,"errorMessage":"bootstrap service '{name}' cannot be both masked and enabled","messagePattern":"bootstrap service '(.+?)' cannot be both masked and enabled","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"src/system/services.rs","lineNumber":232,"sourceCode":"}\n\nimpl ServiceRequest {\n    #[cfg(test)]\n    fn from_toml(name: String, config: ServiceTomlConfig) -> Result<Self> {\n        Self::from_toml_with_origin(name, config, None)\n    }\n\n    fn from_toml_with_origin(\n        name: String,\n        config: ServiceTomlConfig,\n        origin: Option<ResourceOrigin>,\n    ) -> Result<Self> {\n        let unit = normalize_unit_name(&name)?;\n        if config.masked && config.state == ServiceState::Running {\n            bail!(\"bootstrap service '{name}' cannot be both masked and running\");\n        }\n        if config.masked && config.enabled {\n            bail!(\"bootstrap service '{name}' cannot be both masked and enabled\");\n        }\n        Ok(Self {\n            name,\n            unit,\n            state: config.state,\n            enabled: config.enabled,\n            masked: config.masked,\n            on_change: config.on_change,\n            origin,\n            inspection: None,\n        })\n    }\n\n    pub(crate) fn plan(&self) -> ResourcePlan {\n        let id = ResourceId::new(\"service\", &self.name);\n        let desired = self.desired();\n        let Some(inspection) = &self.inspection else {\n            return self.with_origin(ResourcePlan::new(","sourceCodeStart":214,"sourceCodeEnd":250,"githubUrl":"https://github.com/jdx/mise/blob/6f52dcdf99e282ef7a7db68c81301fa4618d0f79/src/system/services.rs#L214-L250","documentation":"The second mask-combination check in from_toml_with_origin (src/system/services.rs:232): `masked = true` together with `enabled = true` is rejected. A masked unit is symlinked to /dev/null; enabling it would create a symlink in the wants/ tree pointing at nothing, which is at best noise and at worst a boot-time failure, so the pair is invalid by design.","triggerScenarios":"A service declaration with both `masked = true` and `enabled = true` (enabled defaults may also come into play depending on the config body). Caught during request construction from any config layer.","commonSituations":"Hardening a machine by masking a service while a copied template still sets enabled = true; enabling a unit and later masking it in another config layer without clearing enabled; defaults merged from a base config producing both flags.","solutions":["For masking: set enabled = false (masking makes enabled moot anyway)","For enabling: set masked = false","Check layered configs — one layer may contribute enabled = true while another adds masked = true","Re-run bootstrap after the flags are mutually consistent"],"exampleFix":"# before\n[bootstrap.services.debug-shell]\nmasked = true\nenabled = true    # -> bail\n# after\n[bootstrap.services.debug-shell]\nmasked = true\nenabled = false","handlingStrategy":"validation","validationCode":"# masked + enabled is always invalid — catch it in config lint\npython3 - <<'PY'\nimport tomllib\nsvc = tomllib.load(open('mise.toml','rb')).get('bootstrap',{}).get('services',{})\nif isinstance(svc, dict):\n    for name, body in svc.items():\n        if isinstance(body,dict) and body.get('masked') and body.get('enabled'):\n            print(f\"service {name}: masked cannot be enabled\")\nPY","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Always write enabled = false next to masked = true to make intent explicit","When hardening by masking, audit copied templates for leftover enabled = true","Check layered configs: one layer may inject enabled while another masks"],"tags":["bootstrap","services","systemd","validation","config","mise"],"backgroundTag":"invalid-config-combination","analyzedSha":"6f52dcdf99e282ef7a7db68c81301fa4618d0f79","analyzedAt":"2026-08-22T10:14:23.840Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-08T10:18:20.063Z"}