Hmbown/CodeWhale · error · anyhow::Error
RRULE must include FREQ
Error message
RRULE must include FREQ
What it means
After collecting KEY=VALUE segments, parse_rrule looks up the `FREQ` key (case-insensitive) and finds none. FREQ is the mandatory first decision (which schedule variant to build), so an RRULE without it cannot be interpreted at all. Empty segments were already skipped, so a string of only separators or whitespace also lands here.
Source
Thrown at crates/tui/src/automation_manager.rs:310
let Some((k, v)) = item.split_once('=') else {
bail!("Invalid RRULE segment '{item}'");
};
parts.insert(k.trim().to_ascii_uppercase(), v.trim().to_string());
}
let freq = match parts
.get("FREQ")
.map(|value| value.trim().to_ascii_uppercase())
.as_deref()
{
Some("ONCE") => return parse_once_schedule(&parts),
Some("HOURLY") => AutomationFrequency::Hourly,
Some("WEEKLY") => AutomationFrequency::Weekly,
Some("CRON") => return parse_cron_schedule(&parts),
Some(other) => {
bail!("Unsupported RRULE FREQ '{other}'. Supported: ONCE, HOURLY, WEEKLY, and CRON")
}
None => bail!("RRULE must include FREQ"),
};
match freq {
AutomationFrequency::Hourly => {
for key in parts.keys() {
if key != "FREQ"
&& key != "INTERVAL"
&& key != "BYDAY"
&& key != "BYHOUR"
&& key != "BYMINUTE"
{
bail!(
"Unsupported RRULE field '{key}' for HOURLY. Allowed: FREQ,INTERVAL,BYDAY,BYHOUR,BYMINUTE"
);
}
}
let interval_hours = parts
.get("INTERVAL")View on GitHub (pinned to 0c42157ee5)
Solutions
- Start every rule with a FREQ part: `FREQ=ONCE|HOURLY|WEEKLY|CRON;...`.
- Validate presence before parsing: `rrule.split(';').any(|p| p.trim().to_ascii_uppercase().starts_with("FREQ="))`.
- If the rule is user-supplied, reject it at the UI boundary with the supported-grammar hint.
Example fix
// before
let sched = AutomationSchedule::parse_rrule("BYDAY=MO;BYHOUR=9")?; // bails: RRULE must include FREQ
// after
let sched = AutomationSchedule::parse_rrule("FREQ=WEEKLY;BYDAY=MO;BYHOUR=9;BYMINUTE=0")?; Defensive patterns
Strategy: validation
Validate before calling
if !rrule
.split(';')
.any(|p| p.trim().to_ascii_uppercase().starts_with("FREQ="))
{
anyhow::bail!("RRULE must start with FREQ=ONCE|HOURLY|WEEKLY|CRON");
} Type guard
fn has_freq_part(rrule: &str) -> bool {
rrule.split(';').any(|p| p.trim().to_ascii_uppercase().starts_with("FREQ="))
} Try / catch
match AutomationSchedule::parse_rrule(&rrule) {
Ok(s) => s,
Err(e) if e.to_string().contains("must include FREQ") => { /* prepend FREQ=... or re-prompt */ return Err(e) }
Err(e) => return Err(e),
} Prevention
- Always construct RRULEs starting from a FREQ part chosen by enum, not string parts.
- Require non-empty rules in config validation.
- Unit-test your RRULE builder emits FREQ first.
When it happens
Trigger: Calling parse_rrule with `"BYDAY=MO;BYHOUR=9"`, `""`, `";;;"`, or a rule where FREQ is misspelled (`FREQ=` empty also yields no usable value once consumed elsewhere — the key must exist).
Common situations: Building RRULE strings programmatically and forgetting to append the FREQ part; user config with only the day/time fields; strings that got truncated before FREQ.
Related errors
- Invalid RRULE segment '{item}'
- Unsupported RRULE FREQ '{other}'. Supported: ONCE, HOURLY, W
- Unsupported RRULE field '{key}' for HOURLY. Allowed: FREQ,IN
- INTERVAL must be >= 1 for HOURLY schedules
- BYHOUR must be between 0 and 23
AI-assisted analysis of Hmbown/CodeWhale@0c42157ee5 (2026-08-20).
Data as JSON: /api/errors/7e3ab12928db3d6f.
Report an issue: GitHub.