Hmbown/CodeWhale · error · anyhow::Error

Invalid RRULE segment '{item}'

Error message

Invalid RRULE segment '{item}'

What it means

AutomationSchedule::parse_rrule splits the rule string on ';' and requires every non-empty trimmed segment to contain '='. A segment without '=' cannot be a KEY=VALUE part, so parsing stops immediately with the offending segment named in the message.

Source

Thrown at crates/tui/src/automation_manager.rs:293

        byday: Vec<Weekday>,
        byhour: u32,
        byminute: u32,
    },
    Cron {
        expr: String,
    },
}

impl AutomationSchedule {
    pub fn parse_rrule(rrule: &str) -> Result<Self> {
        let mut parts: BTreeMap<String, String> = BTreeMap::new();
        for raw in rrule.split(';') {
            let item = raw.trim();
            if item.is_empty() {
                continue;
            }
            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"),
        };

View on GitHub (pinned to 0c42157ee5)

Solutions

  1. Fix the segment to KEY=VALUE form, e.g. `FREQ=WEEKLY;BYDAY=MO,WE;BYHOUR=9;BYMINUTE=30`.
  2. Split and lint each `;`-separated part with `part.split_once('=')` before submitting the schedule.
  3. Use the documented grammar from crates/tui/src/tools/automation.rs (ONCE/HOURLY/WEEKLY/CRON forms) as the template.

Example fix

// before
let sched = AutomationSchedule::parse_rrule("FREQ=WEEKLY;MO,WE")?; // bails: segment 'MO,WE'

// after
let sched = AutomationSchedule::parse_rrule("FREQ=WEEKLY;BYDAY=MO,WE;BYHOUR=9;BYMINUTE=30")?;
Defensive patterns

Strategy: validation

Validate before calling

fn rrule_segments_wellformed(rrule: &str) -> bool {
    rrule.split(';')
        .map(str::trim)
        .filter(|s| !s.is_empty())
        .all(|s| s.split_once('=').is_some())
}

Type guard

fn is_parseable_rrule_shape(rrule: &str) -> bool {
    rrule.split(';').filter(|s| !s.trim().is_empty()).all(|s| s.split_once('=').is_some())
        && rrule.to_ascii_uppercase().contains("FREQ=")
}

Try / catch

match AutomationSchedule::parse_rrule(&rrule) {
    Ok(s) => s,
    Err(e) if e.to_string().contains("Invalid RRULE segment") => { /* show KEY=VALUE grammar hint */ return Err(e) }
    Err(e) => return Err(e),
}

Prevention

When it happens

Trigger: Passing an RRULE like `FREQ=WEEKLY;MO,WE;BYHOUR=9` (bare day list without the BYDAY= key), `FREQ WEEKLY` (wrong separator), or a trailing scrap like `FREQ=HOURLY;INTERVAL=2;;junk` to parse_rrule.

Common situations: Hand-writing RRULE strings in automation config or the automation tool; concatenating segments without the '='; copying RRULE text from calendar apps that omit values for empty parts.

Related errors


AI-assisted analysis of Hmbown/CodeWhale@0c42157ee5 (2026-08-20). Data as JSON: /api/errors/c980cc5fcaa88296. Report an issue: GitHub.