Hmbown/CodeWhale · error · anyhow::Error

BYMINUTE must be between 0 and 59

Error message

BYMINUTE must be between 0 and 59

What it means

In the HOURLY branch, an optional BYMINUTE anchor must be a valid minute 0–59 (u32, so 60+ fails this check). Like BYHOUR, it pins the initial local wall-clock minute of the anchored cadence and has no meaning outside the valid minute range.

Source

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

                let byday = parts
                    .get("BYDAY")
                    .map(|value| parse_byday(&value.to_ascii_uppercase()))
                    .transpose()?;
                let anchor_hour = parts
                    .get("BYHOUR")
                    .map(|value| value.parse::<u32>())
                    .transpose()
                    .context("Failed to parse BYHOUR")?;
                let anchor_minute = parts
                    .get("BYMINUTE")
                    .map(|value| value.parse::<u32>())
                    .transpose()
                    .context("Failed to parse BYMINUTE")?;
                if anchor_hour.is_some_and(|hour| hour > 23) {
                    bail!("BYHOUR must be between 0 and 23");
                }
                if anchor_minute.is_some_and(|minute| minute > 59) {
                    bail!("BYMINUTE must be between 0 and 59");
                }
                Ok(Self::Hourly {
                    interval_hours,
                    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")

View on GitHub (pinned to 0c42157ee5)

Solutions

  1. Use a minute 0–59 (`BYMINUTE=0` for the top of the hour).
  2. Validate the numeric range in the form/config layer before constructing the RRULE.
  3. For second-level precision use `FREQ=CRON;EXPR=... ` — note cron here still fires at minute granularity, so express minute-level needs as-is.

Example fix

// before
let s = AutomationSchedule::parse_rrule("FREQ=HOURLY;BYMINUTE=60")?; // bails: 0-59

// after
let s = AutomationSchedule::parse_rrule("FREQ=HOURLY;BYMINUTE=0")?;
Defensive patterns

Strategy: validation

Validate before calling

let minute: u32 = minute_input;
assert!(minute <= 59, "BYMINUTE must be 0-59");
let rrule = format!("FREQ=HOURLY;BYMINUTE={minute}");

Type guard

fn valid_minute(m: u32) -> bool { m <= 59 }

Try / catch

match AutomationSchedule::parse_rrule(&rrule) {
    Ok(s) => s,
    Err(e) if e.to_string().starts_with("BYMINUTE must be between 0 and 59") => { /* re-prompt for a 0-59 minute */ return Err(e) }
    Err(e) => return Err(e),
}

Prevention

When it happens

Trigger: parse_rrule("FREQ=HOURLY;BYMINUTE=60") or BYMINUTE=90/999 in a HOURLY rule.

Common situations: Using 60 for 'top of the next hour'; leap-second-style values like 60; copy-paste of seconds into the minute field.

Related errors


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