{"record":{"id":"8ddb96781d5eb133","repo":"Hmbown/CodeWhale","slug":"unsupported-rrule-field-key-for-once-allowed","errorCode":null,"errorMessage":"Unsupported RRULE field '{key}' for ONCE. Allowed: FREQ,AT","messagePattern":"Unsupported RRULE field '(.+?)' for ONCE\\. Allowed: FREQ,AT","errorType":"validation","errorClass":"anyhow::Error","httpStatus":null,"severity":"error","filePath":"crates/tui/src/automation_manager.rs","lineNumber":701,"sourceCode":"            \"TU\" => Weekday::Tue,\n            \"WE\" => Weekday::Wed,\n            \"TH\" => Weekday::Thu,\n            \"FR\" => Weekday::Fri,\n            \"SA\" => Weekday::Sat,\n            \"SU\" => Weekday::Sun,\n            other => bail!(\"Invalid BYDAY value '{other}'\"),\n        };\n        if !days.contains(&day) {\n            days.push(day);\n        }\n    }\n    Ok(days)\n}\n\nfn parse_once_schedule(parts: &BTreeMap<String, String>) -> Result<AutomationSchedule> {\n    for key in parts.keys() {\n        if key != \"FREQ\" && key != \"AT\" {\n            bail!(\"Unsupported RRULE field '{key}' for ONCE. Allowed: FREQ,AT\");\n        }\n    }\n    let raw_at = parts\n        .get(\"AT\")\n        .ok_or_else(|| anyhow::anyhow!(\"ONCE schedules require AT\"))?;\n    let at = parse_once_at(raw_at)?;\n    Ok(AutomationSchedule::Once { at })\n}\n\nfn parse_cron_schedule(parts: &BTreeMap<String, String>) -> Result<AutomationSchedule> {\n    for key in parts.keys() {\n        if key != \"FREQ\" && key != \"EXPR\" {\n            bail!(\"Unsupported RRULE field '{key}' for CRON. Allowed: FREQ,EXPR\");\n        }\n    }\n    let expr = parts\n        .get(\"EXPR\")\n        .map(|value| value.trim().to_string())","sourceCodeStart":683,"sourceCodeEnd":719,"githubUrl":"https://github.com/Hmbown/CodeWhale/blob/73e0f67d83c59909b571efdfc88c4bc28c309cb1/crates/tui/src/automation_manager.rs#L683-L719","documentation":"parse_once_schedule whitelists the RRULE keys allowed for a ONCE schedule: only FREQ and AT. Any other key in the parsed key/value parts bails with this message listing the allowed set. It exists so users get a precise rejection instead of a silently ignored field (e.g. BYDAY on a one-shot schedule would be meaningless).","triggerScenarios":"AutomationSchedule::parse with FREQ=ONCE plus any key besides AT — e.g. BYDAY, BYHOUR, INTERVAL, or EXPR included in the RRULE string.","commonSituations":"Copying an RRULE from a recurring schedule and changing only FREQ to ONCE while leaving INTERVAL/BYDAY behind; pasting a full iCalendar RRULE with extra fields.","solutions":["Remove all fields except FREQ and AT from the ONCE RRULE.","Move recurring-only fields (INTERVAL, BYDAY, BYHOUR, BYMINUTE) to a HOURLY/WEEKLY schedule instead.","Use FREQ=CRON with EXPR if you need richer recurrence semantics."],"exampleFix":"// before\nFREQ=ONCE;AT=2026-09-21T09:00;BYDAY=MO\n// after\nFREQ=ONCE;AT=2026-09-21T09:00","handlingStrategy":"validation","validationCode":"const ONCE_KEYS: [&str; 2] = [\"FREQ\", \"AT\"];\nif !parts.keys().all(|k| ONCE_KEYS.contains(&k.as_str())) {\n    return Err(\"ONCE schedules allow only FREQ and AT\");\n}","typeGuard":null,"tryCatchPattern":"match AutomationSchedule::parse(rrule) {\n    Ok(s) => save(s),\n    Err(e) if e.to_string().contains(\"for ONCE\") => strip_unknown_fields_and_retry(),\n    Err(e) => report(e),\n}","preventionTips":["Build RRULE strings from a fixed key set rather than concatenating user input.","When converting a recurring schedule to ONCE, drop INTERVAL/BYDAY/BYHOUR/BYMINUTE.","Validate the RRULE key set per FREQ value before persisting."],"tags":["validation","rrule","scheduling"],"backgroundTag":"unsupported-config-value","analyzedSha":"73e0f67d83c59909b571efdfc88c4bc28c309cb1","analyzedAt":"2026-09-22T01:30:00.501Z","contentChangedAt":"2026-09-22T01:30:00.501Z","schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}