{"record":{"id":"194cf48fe9c3fc72","repo":"jdx/mise","slug":"agent-agent-name-start-calendar-interval-mus-194cf4","errorCode":null,"errorMessage":"agent '{agent_name}' `start_calendar_interval` must not be empty","messagePattern":"agent '(.+?)' `start_calendar_interval` must not be empty","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"src/system/launchd.rs","lineNumber":175,"sourceCode":"        {\n            bail!(\"agent '{agent_name}' `start_calendar_interval` must set at least one field\");\n        }\n        validate_range(agent_name, \"minute\", self.minute, 0, 59)?;\n        validate_range(agent_name, \"hour\", self.hour, 0, 23)?;\n        validate_range(agent_name, \"day\", self.day, 1, 31)?;\n        validate_range(agent_name, \"weekday\", self.weekday, 0, 7)?;\n        validate_range(agent_name, \"month\", self.month, 1, 12)?;\n        Ok(())\n    }\n}\n\nimpl LaunchdCalendarIntervals {\n    fn validate(&self, agent_name: &str) -> Result<()> {\n        match self {\n            Self::Single(interval) => interval.validate(agent_name),\n            Self::Multiple(intervals) => {\n                if intervals.is_empty() {\n                    bail!(\"agent '{agent_name}' `start_calendar_interval` must not be empty\");\n                }\n                for interval in intervals {\n                    interval.validate(agent_name)?;\n                }\n                Ok(())\n            }\n        }\n    }\n}\n\nfn validate_range(\n    agent_name: &str,\n    field: &str,\n    value: Option<u8>,\n    min: u8,\n    max: u8,\n) -> Result<()> {\n    if let Some(value) = value","sourceCodeStart":157,"sourceCodeEnd":193,"githubUrl":"https://github.com/jdx/mise/blob/9dcfcaa0dc8747a2577d3270b69bb9d8313b2807/src/system/launchd.rs#L157-L193","documentation":"start_calendar_interval also accepts an array of interval tables (LaunchdCalendarIntervals::Multiple). An empty array — zero intervals — is rejected because an agent would be declared as calendar-scheduled with no schedule at all; the agent is skipped with a warning. This is the array-form counterpart of the 'must set at least one field' check.","triggerScenarios":"Writing start_calendar_interval = [] in a [bootstrap.macos.launchd.agents.<name>] table, or a template loop that renders zero interval entries into the array.","commonSituations":"Templating that yields an empty list when a schedule variable is unset; scaffolding that pre-declares the key; merging configs where interval entries were removed but the key remained.","solutions":["Remove the start_calendar_interval key entirely if the agent has no calendar schedule","Or add at least one interval table to the array: start_calendar_interval = [{ hour = 3 }]","Guard templating so an unset schedule omits the key instead of emitting an empty array"],"exampleFix":"# before\n[bootstrap.macos.launchd.agents.backup]\nprogram = \"/usr/local/bin/backup\"\nstart_calendar_interval = []\n\n# after\n[bootstrap.macos.launchd.agents.backup]\nprogram = \"/usr/local/bin/backup\"\nstart_calendar_interval = [{ hour = 3, minute = 0 }]","handlingStrategy":"validation","validationCode":"python3 - <<'EOF'\nimport tomllib,sys\nc=tomllib.load(open('mise.toml','rb'))\nfor name,agent in (c.get('bootstrap',{}).get('macos',{}).get('launchd',{}).get('agents',{}) or {}).items():\n    iv=agent.get('start_calendar_interval')\n    if isinstance(iv,list) and not iv: sys.exit(f'agent {name}: empty start_calendar_interval array')\nEOF","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Omit start_calendar_interval entirely when no schedule is wanted","In templates, emit the key only when the schedule list is non-empty","Prefer the single-table form for one schedule; arrays are only for multiple intervals"],"tags":["mise","macos","launchd","scheduling","empty-value"],"backgroundTag":"config-validation-failed","analyzedSha":"9dcfcaa0dc8747a2577d3270b69bb9d8313b2807","analyzedAt":"2026-08-17T14:28:50.624Z","schemaVersion":2},"datasetVersion":"2026-08-21T18:17:14.833Z"}