Hmbown/CodeWhale · error · anyhow::Error
Unable to compute next CRON run within 5 years
Error message
Unable to compute next CRON run within 5 years
What it means
Thrown by the CRON branch of next_after_in_timezone when a minute-by-minute search of MAX_CRON_SEARCH_MINUTES (60*24*366*5, five years including a leap-day budget) finds no local datetime matching the expression strictly after 'after'. With standard cron OR semantics between day-of-month and day-of-week, this requires the expression's firing dates to be absent from the entire window, e.g. a Feb-29-only schedule in a stretch without a leap day, or a search start near chrono's datetime limits.
Source
Thrown at crates/tui/src/automation_manager.rs:547
.and_then(|dt| dt.with_nanosecond(0))
.ok_or_else(|| anyhow::anyhow!("Unable to round CRON search start"))?
.checked_add_signed(Duration::minutes(1))
.ok_or_else(|| anyhow::anyhow!("CRON schedule exceeded its range"))?;
for _ in 0..MAX_CRON_SEARCH_MINUTES {
if cron.matches(candidate_naive)
&& let Some(candidate) = resolve_local_datetime(timezone, candidate_naive)
{
let candidate = candidate.with_timezone(&Utc);
if candidate > after {
return Ok(candidate);
}
}
candidate_naive = candidate_naive
.checked_add_signed(Duration::minutes(1))
.ok_or_else(|| anyhow::anyhow!("CRON schedule exceeded its range"))?;
}
bail!("Unable to compute next CRON run within 5 years");
}
}
}
fn next_after_slot(
&self,
slot: DateTime<Utc>,
anchor_reference: DateTime<Utc>,
) -> Result<Option<DateTime<Utc>>> {
match self {
Self::Once { .. } => Ok(None),
_ => self
.next_after_with_anchor(slot, anchor_reference)
.map(Some),
}
}
}
View on GitHub (pinned to 0c42157ee5)
Solutions
- Rewrite rare-date crons to fire on a date that exists every year, e.g. '0 0 28 2 *' with a leap-day check inside the task
- Drop over-restrictive day fields so at least one match exists per year
- Dry-run parse_rrule plus a next-run computation before activating the automation
- Catch the error and pause the automation rather than letting the scheduler retry every tick
Example fix
// before (may have no Feb 29 within the 5-year window) rrule = "FREQ=CRON;EXPR=0 0 29 2 *" // after (fires every Feb 28; the task itself checks for a real leap day) rrule = "FREQ=CRON;EXPR=0 0 28 2 *"
Defensive patterns
Strategy: validation
Validate before calling
fn cron_next_run_plausible(expr: &str) -> Result<bool, anyhow::Error> {
let rrule = format!("FREQ=CRON;EXPR={expr}");
AutomationSchedule::parse_rrule(&rrule)?; // syntax + impossible-date checks
// Feb-29-only expressions are the classic 5-year-window miss.
let fields: Vec<&str> = expr.split_whitespace().collect();
Ok(!(fields.len() == 5 && fields[2] == "29" && fields[3] == "2" && fields[4] == "*"))
} Try / catch
match manager.update_automation(id, req) {
Ok(rec) => { /* ... */ }
Err(e) if e.to_string().contains("within 5 years") => {
// Expression cannot fire inside the search horizon; pause instead of retrying.
tracing::warn!(%e, "cron automation {id} never matches; pausing");
}
Err(e) => return Err(e),
} Prevention
- Avoid cron expressions whose only firing dates are rarer than once a year
- Remember day-of-month and day-of-week combine with OR, so rarity must come from the month/day fields
- Test rare-date schedules by computing the next run before activation
- Pause rather than delete unreachable automations so config is preserved for repair
When it happens
Trigger: An Active automation with FREQ=CRON;EXPR='0 0 29 2 *' evaluated between 2097 and 2103 (the 2100 century non-leap gap pushes the next Feb 29 more than five years out); or an 'after' timestamp close enough to NaiveDateTime's maximum that the 5-year window cannot complete.
Common situations: Copy-pasted rare-date cron expressions (Feb 29 maintenance jobs) on long-lived installations; tests pinned to far-future dates; schedules running across century boundaries.
Related errors
- Unable to compute next HOURLY run for BYDAY filter
- Unable to compute next WEEKLY run
- Invalid RRULE segment '{item}'
- Unsupported RRULE FREQ '{other}'. Supported: ONCE, HOURLY, W
- RRULE must include FREQ
AI-assisted analysis of Hmbown/CodeWhale@0c42157ee5 (2026-08-20).
Data as JSON: /api/errors/aa13d89babe9b52b.
Report an issue: GitHub.