Hmbown/CodeWhale · error · anyhow::Error

Invalid BYDAY value

Error message

Invalid BYDAY value '{other}'

What it means

parse_byday validates each comma-separated BYDAY token against the two-letter weekday names MO..SU. Any token that is not one of the seven recognized codes (after trim and ASCII uppercase) bails with this message naming the offending value. This runs while parsing an RRULE into an AutomationSchedule, so it fires at schedule-creation time, not at run time.

Solutions

  1. Use only the two-letter codes MO,TU,WE,TH,FR,SA,SU separated by commas.
  2. Strip numeric ordinal prefixes (2MO → MO); ordinal repetition is not supported.
  3. Trim whitespace/localized names and re-save the schedule.

Example fix

// before
FREQ=WEEKLY;BYDAY=1MO,FR
// after
FREQ=WEEKLY;BYDAY=MO,FR
Defensive patterns

Strategy: validation

Validate before calling

const BYDAY_CODES: [&str; 7] = ["MO","TU","WE","TH","FR","SA","SU"];
fn valid_byday(v: &str) -> bool {
    v.split(',').all(|t| BYDAY_CODES.contains(&t.trim().to_ascii_uppercase().as_str()))
}

Try / catch

match AutomationSchedule::parse(rrule) {
    Ok(s) => save(s),
    Err(e) if e.to_string().contains("Invalid BYDAY") => show_day_code_hint(&e),
    Err(e) => report(e),
}

Prevention

When it happens

Trigger: Calling AutomationSchedule::parse with FREQ=WEEKLY (or HOURLY) whose BYDAY contains tokens other than MO,TU,WE,TH,FR,SA,SU — e.g. full names (MONDAY), numeric prefixes (1MO, RRULE ordinals), or stray characters.

Common situations: Users copying standard iCalendar RRULEs that allow ordinal prefixes like 2MO (not supported here); writing MON instead of MO; leaving trailing punctuation or localized weekday abbreviations.

Understand the failure class

Background: Invalid enum value errors: "Unknown type", "Invalid scope", "must be one of" — when a string is not on the library's allowed list — this error's family across 23 libraries.

Related errors


AI-assisted analysis of Hmbown/CodeWhale@73e0f67d83 (2026-09-22). Data as JSON: /api/errors/26d1205fe7dbdbfd. Report an issue: GitHub.

Appendix: source

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

fn resolve_local_datetime<Tz: TimeZone>(
    timezone: &Tz,
    naive: NaiveDateTime,
) -> Option<DateTime<Tz>> {
    timezone.from_local_datetime(&naive).earliest()
}

fn parse_byday(value: &str) -> Result<Vec<Weekday>> {
    let mut days = Vec::new();
    for token in value.split(',') {
        let day = match token.trim().to_ascii_uppercase().as_str() {
            "MO" => Weekday::Mon,
            "TU" => Weekday::Tue,
            "WE" => Weekday::Wed,
            "TH" => Weekday::Thu,
            "FR" => Weekday::Fri,
            "SA" => Weekday::Sat,
            "SU" => Weekday::Sun,
            other => bail!("Invalid BYDAY value '{other}'"),
        };
        if !days.contains(&day) {
            days.push(day);
        }
    }
    Ok(days)
}

fn parse_once_schedule(parts: &BTreeMap<String, String>) -> Result<AutomationSchedule> {
    for key in parts.keys() {
        if key != "FREQ" && key != "AT" {
            bail!("Unsupported RRULE field '{key}' for ONCE. Allowed: FREQ,AT");
        }
    }
    let raw_at = parts
        .get("AT")
        .ok_or_else(|| anyhow::anyhow!("ONCE schedules require AT"))?;
    let at = parse_once_at(raw_at)?;

View on GitHub (pinned to 73e0f67d83)