jdx/mise · error
timer unit ' ' cannot set service-only directive(s)
Error message
timer unit '{name}' cannot set service-only directive(s): {} What it means
When from_toml classifies a unit as a Timer (because a scheduling key is present), service-only directives such as exec_start, type, remain_after_exit, standard_output/standard_error, etc. are not allowed on it. The error lists exactly which offending fields were set, since systemd defines those on the paired service unit, not the timer.
Solutions
- Remove the listed service-only directives from the timer entry — mise generates the paired service unit itself
- If you need exec_start and its options, split into two entries: a timer entry (schedule only) and a service entry (exec_start etc.)
- Check each named field in the error message and delete it from the timer's TOML table
Example fix
# before (mise.toml) [systemd."backup.timer"] on_calendar = "daily" exec_start = "/usr/bin/backup" # after [systemd."backup.timer"] on_calendar = "daily"
Defensive patterns
Strategy: validation
Validate before calling
const SERVICE_ONLY: &[&str] = &["exec_start","type","remain_after_exit","standard_output","standard_error"]; // reject timer entries that set any of these
Prevention
- Keep timer entries to scheduling keys only (on_calendar, on_boot_sec, randomized_delay_sec)
- Split timer+service needs into two separate mise.toml unit entries
- Mise generates the paired service automatically — do not duplicate its directives
When it happens
Trigger: Defining a timer unit in mise.toml that sets both a schedule key (on_boot_sec / on_unit_active_sec / on_unit_inactive_sec / on_calendar / randomized_delay_sec) and one or more service-only fields (exec_start, type, remain_after_exit, standard_output, standard_error, ...).
Common situations: Copy-pasting a service block and adding on_calendar to it; misunderstanding that mise generates the timer/service pair automatically; trying to configure the service's stdout through the timer entry.
Understand the failure class
Background: Conflicting config options: "cannot be used together" — configuration validation errors across open-source libraries — this error's family across 162 libraries.
Related errors
- timer unit ' ' must set at least one of `on_boot_sec`…
- bootstrap service ' ' sets , which only applies to `scope =…
- managed path ' ' notifies user-scope bootstrap service ' '…
- service unit ' ' has invalid `nice` value ; expected -20…
- service unit ' ' must set a non-empty `exec_start
AI-assisted analysis of jdx/mise@533346cc37 (2026-09-17).
Data as JSON: /api/errors/eff1e19779ed0424.
Report an issue: GitHub.
Appendix: source
Thrown at src/system/systemd.rs:202
(config.timeout_start_sec.is_some(), "timeout_start_sec"),
(config.timeout_stop_sec.is_some(), "timeout_stop_sec"),
(config.no_new_privileges.is_some(), "no_new_privileges"),
(config.private_tmp.is_some(), "private_tmp"),
(!config.environment.is_empty(), "environment"),
(!config.environment_file.is_empty(), "environment_file"),
(config.nice.is_some(), "nice"),
(config.umask.is_some(), "umask"),
(config.working_directory.is_some(), "working_directory"),
(config.restart.is_some(), "restart"),
(config.restart_sec.is_some(), "restart_sec"),
(config.standard_output.is_some(), "standard_output"),
(config.standard_error.is_some(), "standard_error"),
]
.into_iter()
.filter_map(|(is_set, field)| is_set.then_some(field))
.collect::<Vec<_>>();
if !service_only_fields.is_empty() {
bail!(
"timer unit '{name}' cannot set service-only directive(s): {}",
service_only_fields.join(", ")
);
}
if config.on_boot_sec.is_none()
&& config.on_unit_active_sec.is_none()
&& config.on_unit_inactive_sec.is_none()
&& config.on_calendar.is_none()
{
bail!(
"timer unit '{name}' must set at least one of `on_boot_sec`, \
`on_unit_active_sec`, `on_unit_inactive_sec`, or `on_calendar`"
);
}
}
if let Some(nice) = config.nice
&& !(-20..=19).contains(&nice)
{View on GitHub (pinned to 533346cc37)