Hmbown/CodeWhale · error · anyhow::Error
Unsupported RRULE field '{key}' for CRON. Allowed: FREQ,EXPR
Error message
Unsupported RRULE field '{key}' for CRON. Allowed: FREQ,EXPR What it means
parse_cron_schedule rejects any RRULE key other than FREQ and EXPR for FREQ=CRON. Keys are uppercased before the check, so it is case-insensitive; a missing or empty EXPR produces 'CRON schedules require EXPR' instead.
Source
Thrown at crates/tui/src/automation_manager.rs:615
}
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)?;
Ok(AutomationSchedule::Once { at })
}
fn parse_cron_schedule(parts: &BTreeMap<String, String>) -> Result<AutomationSchedule> {
for key in parts.keys() {
if key != "FREQ" && key != "EXPR" {
bail!("Unsupported RRULE field '{key}' for CRON. Allowed: FREQ,EXPR");
}
}
let expr = parts
.get("EXPR")
.map(|value| value.trim().to_string())
.filter(|value| !value.is_empty())
.ok_or_else(|| anyhow::anyhow!("CRON schedules require EXPR"))?;
ParsedCronExpr::parse(&expr)?;
Ok(AutomationSchedule::Cron { expr })
}
fn parse_once_at(raw: &str) -> Result<DateTime<Utc>> {
let trimmed = raw.trim();
if let Ok(at) = DateTime::parse_from_rfc3339(trimmed) {
return Ok(at.with_timezone(&Utc));
}
for format in ["%Y-%m-%dT%H:%M:%S", "%Y-%m-%dT%H:%M"] {
if let Ok(naive) = NaiveDateTime::parse_from_str(trimmed, format) {View on GitHub (pinned to 0c42157ee5)
Solutions
- Keep only FREQ and EXPR: FREQ=CRON;EXPR=*/17 * * * *
- Encode cadence entirely inside the 5-field EXPR
- Move one-shot times to FREQ=ONCE;AT=...
- Dry-run parse_rrule before persisting
Example fix
// before rrule = "FREQ=CRON;EXPR=*/17 * * * *;INTERVAL=2" // after rrule = "FREQ=CRON;EXPR=*/17 * * * *"
Defensive patterns
Strategy: validation
Validate before calling
fn valid_cron_rrule(rrule: &str) -> bool {
rrule.split(';')
.filter_map(|s| s.split_once('=').map(|(k, _)| k.trim().to_ascii_uppercase()))
.all(|k| k == "FREQ" || k == "EXPR")
} Prevention
- Encode all cadence inside the 5-field EXPR
- Strip RRULE-style extras when converting HOURLY/WEEKLY rules to CRON
- Validate the assembled FREQ=CRON;EXPR=... string with parse_rrule
- Keep one-shot times in FREQ=ONCE;AT=... instead of EXPR
When it happens
Trigger: AutomationSchedule::parse_rrule("FREQ=CRON;EXPR=*/17 * * * *;INTERVAL=2"), or any FREQ=CRON rule carrying BYDAY, BYHOUR, AT, or similar extra keys.
Common situations: Mixing RRULE-style fields into cron rules; converting an HOURLY rule to CRON and forgetting to remove INTERVAL/BYDAY.
Related errors
- Invalid BYDAY value '{other}'
- Unsupported RRULE field '{key}' for ONCE. Allowed: FREQ,AT
- CRON EXPR must have exactly 5 fields: minute hour day-of-mon
- CRON EXPR day-of-month/month combination can never occur
- CRON {field_name} field must not be empty
AI-assisted analysis of Hmbown/CodeWhale@0c42157ee5 (2026-08-20).
Data as JSON: /api/errors/fa3bd608ba343a4d.
Report an issue: GitHub.