jdx/mise · error
user service '{name}' must set `command` or `builtin`
Error message
user service '{name}' must set `command` or `builtin` What it means
Definition validation in user services from_toml_with_executable: the service declared neither a `command` nor a `builtin`, so there is nothing to run or manage. Fires on an incomplete user service block in config.
Source
Thrown at src/system/user_services.rs:100
"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!(
"user service '{name}' names unknown builtin '{builtin_name}'; available: {}",
BUILTIN_NAMES.join(", ")
);
};
description.get_or_insert_with(|| definition.description.to_string());
restart.get_or_insert(definition.restart);
nice = definition.nice;
match executable {
Some(exe) => Some(
std::iter::once(quote_program(&exe.to_string_lossy()))
.chain(definition.args.iter().map(|arg| arg.to_string()))
.collect::<Vec<_>>()
.join(" "),
),View on GitHub (pinned to afd2eddd3a)
Solutions
- Add a `command = "..."` to the entry
- Or set `builtin = "<name>"` to one of the available built-ins (see BUILTIN_NAMES)
- Or remove the entry entirely if not needed
Example fix
// before [[bootstrap.linux.user_services]] name = "my-agent" state = "running" // after [[bootstrap.linux.user_services]] name = "my-agent" command = "my-agent --daemon" state = "running"
Defensive patterns
Strategy: validation
Validate before calling
fn validate_user_service(s: &UserServiceConfig) -> Result<(), String> {
if s.builtin.is_none() && s.command.is_none() {
return Err(format!("user service '{}': must set command or builtin", s.name));
}
Ok(())
} Prevention
- Always pair a user service `name` with either `command` or `builtin`
- Remove stub entries before committing config
- Use schema validation on mise.toml to catch missing fields early
When it happens
Trigger: A user service entry with both `builtin` and `command` absent/empty (the `(None, None)` match arm) at src/system/user_services.rs:100 in `from_toml_with_executable`.
Common situations: Starting an entry with only a `name` and `state`, intending to fill in the command later; commenting out a command and forgetting the entry still parses.
Understand the failure class
Background: "is required", "must be set", "missing required field": configuration validation errors across open-source libraries — this error's family across 36 libraries.
Related errors
- "{path_raw}".{id}: no recognized operation (block, source, o
- brew-cask: command_wrapper requires content or executable
- service unit '{name}' must set a non-empty `exec_start`
- user service '{name}' cannot be masked; use `state = "absent
- user service '{name}': `on_change` only applies to system se
AI-assisted analysis of jdx/mise@afd2eddd3a (2026-09-09).
Data as JSON: /api/errors/672c7aedcef98e0d.
Report an issue: GitHub.