jdx/mise · error
bootstrap service '{name}' cannot be both masked and running
Error message
bootstrap service '{name}' cannot be both masked and running What it means
When building a ServiceRequest from TOML (from_toml_with_origin, src/system/services.rs:229), mise rejects the combination masked = true and state = "running": a masked unit's binary is symlinked to /dev/null, so systemd cannot start it — the desired state is unsatisfiable by construction.
Source
Thrown at src/system/services.rs:229
for request in requests {
request.inspection = Some(inspect_service(&systemctl, &request.unit));
}
}
impl ServiceRequest {
#[cfg(test)]
fn from_toml(name: String, config: ServiceTomlConfig) -> Result<Self> {
Self::from_toml_with_origin(name, config, None)
}
fn from_toml_with_origin(
name: String,
config: ServiceTomlConfig,
origin: Option<ResourceOrigin>,
) -> Result<Self> {
let unit = normalize_unit_name(&name)?;
if config.masked && config.state == ServiceState::Running {
bail!("bootstrap service '{name}' cannot be both masked and running");
}
if config.masked && config.enabled {
bail!("bootstrap service '{name}' cannot be both masked and enabled");
}
Ok(Self {
name,
unit,
state: config.state,
enabled: config.enabled,
masked: config.masked,
on_change: config.on_change,
origin,
inspection: None,
})
}
pub(crate) fn plan(&self) -> ResourcePlan {
let id = ResourceId::new("service", &self.name);View on GitHub (pinned to 6f52dcdf99)
Solutions
- If the service must be masked: set its state to stopped (or omit state) — masking already guarantees it cannot run
- If the service must run: set masked = false (and optionally enabled = true)
- If you only wanted it disabled at boot: use enabled = false instead of masked
- Re-run bootstrap; the request builds and planning proceeds
Example fix
# before [bootstrap.services.telnet] masked = true state = "running" # -> bail # after [bootstrap.services.telnet] masked = true state = "stopped"
Defensive patterns
Strategy: validation
Validate before calling
# masked + running is always invalid — catch it in config lint
python3 - <<'PY'
import tomllib
svc = tomllib.load(open('mise.toml','rb')).get('bootstrap',{}).get('services',{})
if isinstance(svc, dict):
for name, body in svc.items():
if isinstance(body,dict) and body.get('masked') and body.get('state')=='running':
print(f"service {name}: masked cannot be running")
PY Prevention
- masked means cannot run — pair it with state = "stopped" or omit state
- Use enabled = false for boot-time disablement; reserve masked for hard-blocking a unit
- Lint masked/state/enabled combinations in CI over all config layers
When it happens
Trigger: Declaring a service with `masked = true` together with `state = "running"` in any bootstrap config layer. Validated at request-construction time, before the plan or systemctl runs.
Common situations: Copy-pasting a service block and toggling masked for a 'disable it' use case without changing state; merging two config fragments that together set both fields; misunderstanding masked as a softer version of disabled.
Related errors
- bootstrap service '{name}' cannot be both masked and enabled
- invalid bootstrap secret name '{name}': use ASCII letters, d
- conflicting bootstrap service declarations for {name}\n\n f
- managed path '{}' notifies unconfigured bootstrap service '{
- managed path '{}' notifies unconfigured bootstrap service '{
AI-assisted analysis of jdx/mise@6f52dcdf99 (2026-08-22).
Data as JSON: /api/errors/a02e62b8514d428b.
Report an issue: GitHub.