Hmbown/CodeWhale · error · anyhow::Error
CRON EXPR day-of-month/month combination can never occur
Error message
CRON EXPR day-of-month/month combination can never occur
What it means
validate_date_space runs after field parsing when day-of-month is not a wildcard: for each listed month it checks that at least one listed day is <= that month's day count in 2024 (leap) or 2025 (common). If no month/day pair can ever exist, the expression is rejected as unmatchable. '0 0 29 2 *' passes because Feb 29 exists in leap years; '0 0 30 2 *' and '0 0 31 4 *' fail.
Source
Thrown at crates/tui/src/automation_manager.rs:708
day_of_month || weekday
}
}
fn validate_date_space(&self) -> Result<()> {
if self.day_of_month.is_wildcard {
return Ok(());
}
let months = self.month.values();
let days = self.day_of_month.values();
let valid = months.iter().copied().any(|month| {
let common = days_in_month(2025, month);
let leap = days_in_month(2024, month);
days.iter().copied().any(|day| day <= common || day <= leap)
});
if valid {
Ok(())
} else {
bail!("CRON EXPR day-of-month/month combination can never occur")
}
}
}
#[derive(Debug, Clone)]
struct CronField {
values: Vec<u32>,
is_wildcard: bool,
}
impl CronField {
fn parse(raw: &str, min: u32, max: u32, names: CronNameMap, field_name: &str) -> Result<Self> {
let trimmed = raw.trim();
if trimmed.is_empty() {
bail!("CRON {field_name} field must not be empty");
}
let mut values = Vec::new();
let is_wildcard = trimmed == "*";View on GitHub (pinned to 0c42157ee5)
Solutions
- Restrict the month field to months that have the day, e.g. '0 0 31 1,3,5,7,8,10,12 *'
- Or use a range like 28-31 and verify the month length inside the task
- Remember February contributes at most 29; Feb-29-only rules then face the 5-year search limit
- Dry-run parse_rrule to catch this at configuration time
Example fix
// before (April 31 does not exist) rrule = "FREQ=CRON;EXPR=0 0 31 4 *" // after (31st only in 31-day months) rrule = "FREQ=CRON;EXPR=0 0 31 1,3,5,7,8,10,12 *"
Defensive patterns
Strategy: validation
Validate before calling
fn cron_expr_valid(expr: &str) -> bool {
AutomationSchedule::parse_rrule(&format!("FREQ=CRON;EXPR={expr}")).is_ok()
} Prevention
- Generate end-of-month schedules with month-aware logic
- Remember February contributes at most 29 days
- Validate EXPR through parse_rrule before saving
- Prefer ranges like 28-31 plus in-task date checks over a bare 31
When it happens
Trigger: EXPR='0 0 31 4 *' (April 31); '0 0 30 2 *' (Feb 30); '0 0 31 4,6,9,11 *' (day 31 restricted to 30-day months).
Common situations: End-of-month crontabs applied blindly to every month; generated expressions enumerating day 31 for monthly tasks.
Related errors
- Unsupported RRULE field '{key}' for CRON. Allowed: FREQ,EXPR
- CRON EXPR must have exactly 5 fields: minute hour day-of-mon
- CRON {field_name} field must not be empty
- CRON {field_name} field contains an empty list item
- CRON {field_name} step must be >= 1
AI-assisted analysis of Hmbown/CodeWhale@0c42157ee5 (2026-08-20).
Data as JSON: /api/errors/76780cf165d0abd7.
Report an issue: GitHub.