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
The cron parser validates that a schedule's day-of-month field can actually match at least one day of the given month, including leap years (days_in_month(2024, month) is used as the leap-year upper bound). If every listed day-of-month exceeds the maximum possible length of the specified month(s), the combination can never fire and parsing is rejected. This catches schedules like '0 0 31 2 *' (Feb 31) that would otherwise silently never run.
Solutions
- Change the day-of-month to a value that exists in the specified month(s), e.g. '0 0 29 2 *' for leap-year-only Feb
- Widen the month field so the day exists, e.g. '0 0 31 1,3,5,7,8,10,12 *'
- Use a step or range that includes at least one valid day, e.g. '0 0 */30 2 *' (30 does not exist in Feb either — use 1-28 instead)
Example fix
// before schedule = "0 0 31 2 *"; // never occurs // after schedule = "0 0 28 2 *"; // or 29 for leap-year-only
Defensive patterns
Strategy: validation
Validate before calling
fn day_valid_for_month(day: u32, month: u32) -> bool {
let leap = days_in_month(2024, month);
let common = days_in_month(2023, month);
day <= leap || day <= common
}
assert!(day_valid_for_month(29, 2), "Feb 29 is the Feb maximum"); Prevention
- Check day-of-month against the shortest month in your month list before saving
- Remember cron does not clamp day 31 to shorter months
- Test every saved schedule with a 'does it ever fire' checker
When it happens
Trigger: Calling automation save/validation with a cron expression whose day-of-month entries (e.g. 30, 31) all exceed the number of days in the month(s) given in the month field, e.g. '0 0 31 2 *' or '0 0 30 2,4,6 *' where even leap-year Feb (29) is exceeded.
Common situations: Hand-written cron strings copy-pasted from documentation examples ('0 0 31 2 *' is a classic snippet for 'never runs'); assuming cron clamps day 31 to the last day of shorter months as some schedulers do; typo like month 02 with day 30.
Understand the failure class
Background: "Invalid value" and "allowed values are" config errors: what your library rejected and how to fix it — this error's family across 41 libraries.
Related errors
- CRON EXPR must have exactly 5 fields: minute hour…
- CRON field contains an empty list item
- CRON field must not be empty
- CRON range start must be <= end
- CRON step must be >= 1
AI-assisted analysis of Hmbown/CodeWhale@73e0f67d83 (2026-09-22).
Data as JSON: /api/errors/76780cf165d0abd7.
Report an issue: GitHub.
Appendix: source
Thrown at crates/tui/src/automation_manager.rs:807
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 73e0f67d83)