Hmbown/CodeWhale · error · anyhow::Error
Unable to compute next WEEKLY run
Error message
Unable to compute next WEEKLY run
What it means
Thrown by the WEEKLY branch of next_after_in_timezone after scanning 15 consecutive days (day_offset 0..15) without finding a BYDAY/BYHOUR/BYMINUTE wall time that resolves to a real local instant strictly after 'after'. Any non-empty BYDAY recurs within 7 days, so through parse_rrule (which enforces non-empty WEEKLY BYDAY) this is a defensive exhaustion guard; it becomes reachable only when every matching wall time in the window fails to resolve in local time (DST spring-forward gap) or the schedule was constructed directly with an empty byday vec.
Source
Thrown at crates/tui/src/automation_manager.rs:522
byday,
byhour,
byminute,
} => {
for day_offset in 0..15 {
let date = local_after.date_naive() + Duration::days(i64::from(day_offset));
if !byday.contains(&date.weekday()) {
continue;
}
let Some(candidate_naive) = date.and_hms_opt(*byhour, *byminute, 0) else {
continue;
};
if let Some(candidate) = resolve_local_datetime(timezone, candidate_naive)
&& candidate.with_timezone(&Utc) > after
{
return Ok(candidate.with_timezone(&Utc));
}
}
bail!("Unable to compute next WEEKLY run");
}
Self::Cron { expr } => {
let cron = ParsedCronExpr::parse(expr)?;
let mut candidate_naive = local_after
.naive_local()
.with_second(0)
.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);View on GitHub (pinned to 0c42157ee5)
Solutions
- If constructing Weekly directly, reject an empty byday before computing the next run
- Route schedule creation through parse_rrule so WEEKLY BYDAY non-emptiness is enforced
- Shift BYHOUR/BYMINUTE away from the local DST gap hour if the error appears seasonally
- If reached via parse_rrule, report it as a bug with the timezone and rrule
Example fix
// before (direct construction with no days)
let schedule = AutomationSchedule::Weekly { byday: vec![], byhour: 9, byminute: 0 };
// after (validate before use)
if byday.is_empty() {
anyhow::bail!("WEEKLY schedule needs at least one BYDAY day");
} Defensive patterns
Strategy: validation
Validate before calling
fn weekly_schedule_reachable(rrule: &str) -> Result<bool, anyhow::Error> {
if let AutomationSchedule::Weekly { byday, byhour, byminute } =
AutomationSchedule::parse_rrule(rrule)?
{
if byday.is_empty() {
return Ok(false);
}
let any_monday = chrono::NaiveDate::from_ymd_opt(2025, 1, 6).unwrap()
.and_hms_opt(byhour, byminute, 0).unwrap();
if chrono::Local.from_local_datetime(&any_monday).earliest().is_none() {
return Ok(false); // wall time falls in a DST gap
}
}
Ok(true)
} Try / catch
match manager.update_automation(id, req) {
Ok(record) => { /* ... */ }
Err(e) if e.to_string().contains("next WEEKLY run") => {
tracing::warn!(%e, "unreachable WEEKLY automation {id}; check BYDAY/time");
}
Err(e) => return Err(e),
} Prevention
- Create schedules through parse_rrule rather than enum literals so BYDAY non-emptiness is enforced
- Reject empty BYDAY at the UI or tool boundary
- Keep automation wall times away from 02:00-03:00 local to dodge DST gaps
- Capture the timezone in reports when this fires so maintainers can reproduce
When it happens
Trigger: Constructing AutomationSchedule::Weekly directly with byday: vec![] instead of going through parse_rrule; or a timezone where resolve_local_datetime (from_local_datetime(...).earliest()) returns None for the BYHOUR/BYMINUTE on every listed weekday inside the 15-day window (FREQ=WEEKLY;BYDAY=SU;BYHOUR=2;BYMINUTE=30 only skirts this on the single spring-forward Sunday, since the following Sunday resolves).
Common situations: Programmatic construction of the schedule enum rather than parse_rrule; unit tests building Weekly literals with no days; sandboxed environments with exotic timezone data.
Related errors
- Unable to compute next anchored HOURLY run
- Unable to compute next HOURLY run for BYDAY filter
- 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/c4e9a954b1343c13.
Report an issue: GitHub.