{"record":{"id":"17fe54615ee8cf4e","repo":"jdx/mise","slug":"timer-unit-name-must-set-at-least-one-of-on-b","errorCode":null,"errorMessage":"timer unit '{name}' must set at least one of `on_boot_sec`, `on_unit_active_sec`, `on_unit_inactive_sec`, or `on_calendar`","messagePattern":"timer unit '(.+?)' must set at least one of `on_boot_sec`, `on_unit_active_sec`, `on_unit_inactive_sec`, or `on_calendar`","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"src/system/systemd.rs","lineNumber":212,"sourceCode":"                (config.restart_sec.is_some(), \"restart_sec\"),\n                (config.standard_output.is_some(), \"standard_output\"),\n                (config.standard_error.is_some(), \"standard_error\"),\n            ]\n            .into_iter()\n            .filter_map(|(is_set, field)| is_set.then_some(field))\n            .collect::<Vec<_>>();\n            if !service_only_fields.is_empty() {\n                bail!(\n                    \"timer unit '{name}' cannot set service-only directive(s): {}\",\n                    service_only_fields.join(\", \")\n                );\n            }\n            if config.on_boot_sec.is_none()\n                && config.on_unit_active_sec.is_none()\n                && config.on_unit_inactive_sec.is_none()\n                && config.on_calendar.is_none()\n            {\n                bail!(\n                    \"timer unit '{name}' must set at least one of `on_boot_sec`, \\\n                     `on_unit_active_sec`, `on_unit_inactive_sec`, or `on_calendar`\"\n                );\n            }\n        }\n        if let Some(nice) = config.nice\n            && !(-20..=19).contains(&nice)\n        {\n            bail!(\"service unit '{name}' has invalid `nice` value {nice}; expected -20 through 19\");\n        }\n        if let Some(umask) = &config.umask\n            && !valid_umask(umask)\n        {\n            bail!(\n                \"service unit '{name}' has invalid `umask` value '{umask}'; expected an octal access mask from 0000 through 0777\"\n            );\n        }\n        let wanted_by = config.wanted_by.unwrap_or_else(|| match kind {","sourceCodeStart":194,"sourceCodeEnd":230,"githubUrl":"https://github.com/jdx/mise/blob/afd2eddd3a50c16190efc1c7e94404b48f72af57/src/system/systemd.rs#L194-L230","documentation":"A unit classified as a Timer must specify at least one scheduling directive. If none of `on_boot_sec`, `on_unit_active_sec`, `on_unit_inactive_sec`, or `on_calendar` is set, `from_toml` bails because the timer would never trigger.","triggerScenarios":"Declaring `[systemd.<name>.timer]` (or a unit with a service-only-field-free config that had `randomized_delay_sec`, making kind Timer) without any of the four schedule keys.","commonSituations":"Creating a timer skeleton and forgetting the schedule; commenting out `on_calendar` while testing; copying a service block and only renaming it `.timer`.","solutions":["Add a schedule, e.g. `on_calendar = \"daily\"` or `on_boot_sec = 30`.","Use `on_unit_active_sec`/`on_unit_inactive_sec` for relative periodic triggers.","If no schedule is wanted, make it a plain service instead by adding `exec_start` and removing timer-only fields like `randomized_delay_sec`."],"exampleFix":"# before\n[systemd.backup.timer]\n# no schedule set\n\n# after\n[systemd.backup.timer]\non_calendar = \"*-*-* 03:00:00\"","handlingStrategy":"validation","validationCode":"const TIMER_KEYS: &[&str] = &[\"on_boot_sec\", \"on_unit_active_sec\", \"on_unit_inactive_sec\", \"on_calendar\"];\nfn timer_has_schedule(cfg: &toml::Value) -> bool {\n    TIMER_KEYS.iter().any(|k| cfg.get(k).is_some())\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Every timer block needs one of the four schedule keys — add a CI lint for this.","Don't leave schedule keys commented out in committed configs.","Start from a template that includes `on_calendar`."],"tags":["systemd","validation","missing-field","timers"],"backgroundTag":"missing-required-config-field","analyzedSha":"afd2eddd3a50c16190efc1c7e94404b48f72af57","analyzedAt":"2026-09-09T01:38:25.179Z","contentChangedAt":"2026-09-09T01:38:25.179Z","schemaVersion":2},"datasetVersion":"2026-09-14T00:17:10.932Z"}