Hmbown/CodeWhale · error · anyhow::Error
BYDAY cannot be empty for WEEKLY schedules
Error message
BYDAY cannot be empty for WEEKLY schedules
What it means
A defensive guard in the WEEKLY branch: BYDAY is present and parse_byday returned Ok with an empty weekday vector, meaning no day of week would ever match. In practice parse_byday rejects each empty/unknown token with 'Invalid BYDAY value', so reaching this requires a BYDAY value that tokenizes to zero entries — it protects next-run computation from looping forever on an unsatisfiable schedule.
Source
Thrown at crates/tui/src/automation_manager.rs:376
byday,
anchor_hour,
anchor_minute,
})
}
AutomationFrequency::Weekly => {
for key in parts.keys() {
if key != "FREQ" && key != "BYDAY" && key != "BYHOUR" && key != "BYMINUTE" {
bail!(
"Unsupported RRULE field '{key}' for WEEKLY. Allowed: FREQ,BYDAY,BYHOUR,BYMINUTE"
);
}
}
let byday_raw = parts
.get("BYDAY")
.ok_or_else(|| anyhow::anyhow!("WEEKLY schedules require BYDAY"))?;
let byday = parse_byday(&byday_raw.to_ascii_uppercase())?;
if byday.is_empty() {
bail!("BYDAY cannot be empty for WEEKLY schedules");
}
let byhour = parts
.get("BYHOUR")
.ok_or_else(|| anyhow::anyhow!("WEEKLY schedules require BYHOUR"))?
.parse::<u32>()
.context("Failed to parse BYHOUR")?;
let byminute = parts
.get("BYMINUTE")
.ok_or_else(|| anyhow::anyhow!("WEEKLY schedules require BYMINUTE"))?
.parse::<u32>()
.context("Failed to parse BYMINUTE")?;
if byhour > 23 {
bail!("BYHOUR must be between 0 and 23");
}
if byminute > 59 {
bail!("BYMINUTE must be between 0 and 59");
}View on GitHub (pinned to 0c42157ee5)
Solutions
- Provide at least one valid day code (MO,TU,WE,TH,FR,SA,SU): `FREQ=WEEKLY;BYDAY=MO,SU;...`.
- If no days are selected, either block submission in the UI or convert to a CRON/HOURLY rule instead.
- Lint WEEKLY rules for a non-empty, comma-separated, all-caps day list before parsing.
Example fix
// before
let rrule = format!("FREQ=WEEKLY;BYDAY={days};BYHOUR=9;BYMINUTE=0"); // days == "" -> error path
// after
if days.is_empty() {
anyhow::bail!("select at least one weekday");
}
let rrule = format!("FREQ=WEEKLY;BYDAY={days};BYHOUR=9;BYMINUTE=0"); Defensive patterns
Strategy: validation
Validate before calling
if !rrule
.split(';')
.any(|p| p.trim().to_ascii_uppercase().starts_with("BYDAY="))
|| rrule.split(';').find(|p| p.trim().to_ascii_uppercase().starts_with("BYDAY=")).is_some_and(|p| p[6..].trim().is_empty())
{
anyhow::bail!("WEEKLY schedules need at least one day: BYDAY=MO,TU,...");
} Type guard
fn weekly_has_days(rrule: &str) -> bool {
rrule.split(';').find_map(|p| p.trim().strip_prefix("BYDAY=").or_else(|| p.trim().strip_prefix("BYDAY=")))
.is_some_and(|v| v.split(',').any(|t| !t.trim().is_empty()))
} Try / catch
match AutomationSchedule::parse_rrule(&rrule) {
Ok(s) => s,
Err(e) if e.to_string().contains("BYDAY cannot be empty") => { /* require a weekday selection */ return Err(e) }
Err(e) => return Err(e),
} Prevention
- Require at least one selected weekday in schedule forms before submit.
- Skip emitting the BYDAY key when no days are chosen rather than writing an empty value.
- Validate day tokens against MO,TU,WE,TH,FR,SA,SU.
When it happens
Trigger: parse_rrule("FREQ=WEEKLY;BYDAY=;BYHOUR=9;BYMINUTE=0") — a BYDAY key with an empty value generally trips 'Invalid BYDAY value' first; this bail catches any path where the day set ends up empty (future grammar changes, whitespace-only tokens).
Common situations: Config generators emitting `BYDAY=` when no days are selected; form submissions with an empty multi-select for weekdays.
Related errors
- 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
- Unsupported RRULE field '{key}' for HOURLY. Allowed: FREQ,IN
AI-assisted analysis of Hmbown/CodeWhale@0c42157ee5 (2026-08-20).
Data as JSON: /api/errors/d6adb21a09ca30cb.
Report an issue: GitHub.