jdx/mise · error

user service '{name}' cannot be masked; use `state = "absent

Error message

user service '{name}' cannot be masked; use `state = "absent"` to remove it

What it means

User services managed by mise do not support the systemd 'masked' state. If a user service entry sets `masked = true`, parsing fails immediately because masking a user unit is not implemented; the library directs you to remove the service with `state = "absent"` instead. This is a fail-fast validation in `from_toml_with_executable` so bad config is rejected before any system mutation.

Source

Thrown at src/system/user_services.rs:86

        config: ServiceTomlConfig,
        origin: Option<ResourceOrigin>,
    ) -> Result<Self> {
        Self::from_toml_with_executable(name, config, origin, durable_mise_executable())
    }

    fn from_toml_with_executable(
        name: String,
        config: ServiceTomlConfig,
        origin: Option<ResourceOrigin>,
        executable: Option<PathBuf>,
    ) -> Result<Self> {
        if !valid_name(&name) {
            bail!(
                "user service name '{name}' must contain only letters, numbers, '.', '_', or '-'"
            );
        }
        if config.masked {
            bail!("user service '{name}' cannot be masked; use `state = \"absent\"` to remove it");
        }
        if config.on_change != super::services_common::ServiceChangeAction::default() {
            bail!("user service '{name}': `on_change` only applies to system services");
        }
        let mut description = config.description;
        let mut restart = config.restart;
        let mut nice = None;
        let mut unresolved = None;
        let command = match (config.builtin.as_deref(), config.command.as_deref()) {
            (Some(_), Some(_)) => {
                bail!("user service '{name}' sets both `builtin` and `command`; choose one")
            }
            (None, None) => {
                bail!("user service '{name}' must set `command` or `builtin`")
            }
            (Some(builtin_name), None) => {
                let Some(definition) = builtin(builtin_name) else {
                    bail!(

View on GitHub (pinned to afd2eddd3a)

Solutions

  1. Set `masked = false` (or delete the `masked` key) on the user service entry
  2. If the goal is to remove the service, set `state = "absent"` instead of masking
  3. If the goal is to prevent startup, remove the entry from config entirely

Example fix

// before
[[bootstrap.linux.user_services]]
name = "pulseaudio"
command = "pulseaudio"
masked = true

// after
[[bootstrap.linux.user_services]]
name = "pulseaudio"
command = "pulseaudio"
state = "absent"
Defensive patterns

Strategy: validation

Validate before calling

fn validate_user_service(s: &UserServiceConfig) -> Result<(), String> {
    if s.masked {
        return Err(format!("user service '{}' cannot be masked; use state = \"absent\"", s.name));
    }
    Ok(())
}

Prevention

When it happens

Trigger: Declaring a `[bootstrap.*.user_services]` (or equivalent) entry whose parsed config has `masked = true`; raised by `from_toml_with_executable` in src/system/user_services.rs:86 during config parsing.

Common situations: Copying a systemd unit config that used `Masked=true` into a mise user service block; trying to disable a user service by masking it instead of setting its state to absent.

Related errors


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