{"record":{"id":"1df34e8ae9be3894","repo":"Hmbown/CodeWhale","slug":"invalid-cron-field-name-value-raw","errorCode":null,"errorMessage":"Invalid CRON {field_name} value '{raw}'","messagePattern":"Invalid CRON (.+?) value '(.+?)'","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"crates/tui/src/automation_manager.rs","lineNumber":854,"sourceCode":"    fn lookup(self, token: &str) -> Option<u32> {\n        let needle = token.trim().to_ascii_uppercase();\n        self.0\n            .iter()\n            .find_map(|(name, value)| (*name == needle).then_some(*value))\n    }\n}\n\nfn parse_cron_atom(\n    raw: &str,\n    min: u32,\n    max: u32,\n    names: CronNameMap,\n    field_name: &str,\n) -> Result<u32> {\n    let value = names\n        .lookup(raw)\n        .or_else(|| raw.parse::<u32>().ok())\n        .ok_or_else(|| anyhow::anyhow!(\"Invalid CRON {field_name} value '{raw}'\"))?;\n    if !(min..=max).contains(&value) {\n        bail!(\"CRON {field_name} value {value} is out of range {min}-{max}\");\n    }\n    Ok(value)\n}\n\nfn weekday_to_cron(day: Weekday) -> u32 {\n    match day {\n        Weekday::Sun => 0,\n        Weekday::Mon => 1,\n        Weekday::Tue => 2,\n        Weekday::Wed => 3,\n        Weekday::Thu => 4,\n        Weekday::Fri => 5,\n        Weekday::Sat => 6,\n    }\n}\n","sourceCodeStart":836,"sourceCodeEnd":872,"githubUrl":"https://github.com/Hmbown/CodeWhale/blob/8880682c63083a91624de936797efa3ce9e498fd/crates/tui/src/automation_manager.rs#L836-L872","documentation":"Thrown by the TUI automation scheduler while validating a CRON expression (`RRULE:FREQ=CRON;EXPR=...`). `parse_cron_atom` accepts exactly two token shapes for a cron field atom: a recognized 3-letter name (JAN-DEC for month, SUN-SAT for day-of-week, matched case-insensitively after trim) or an unsigned integer; anything else is rejected before the range check. The expression must have exactly 5 fields (minute 0-59, hour 0-23, day-of-month 1-31, month 1-12, day-of-week 0-7).","triggerScenarios":"An automation task with `FREQ=CRON` whose EXPR contains an atom like `MONDAY` (only 3-letter names), `sept.`, `L`/`W`/`?`/`#` (Quartz-only syntax), `-5`, `1e2`, `24x`, or a stray character such as `9..15`. The atom is reached from single values, both endpoints of a range (`a-b`), and the base of steps (`base/step`).","commonSituations":"Pasting a Quartz/Spring cron string (6 fields with seconds, or `L`/`W`/`#`) into the automation config; typing full month/weekday names; copying a cron from a tutorial with a trailing dot or locale-specific characters; using 7-letter names like `OCTOBER`.","solutions":["Rewrite EXPR with exactly 5 space-separated fields: minute hour day-of-month month day-of-week.","Use only 3-letter names (MON, FRI, JAN, OCT) or plain integers — e.g. `EXPR=0 9 * * MON-FRI` instead of `0 9 ? * MONDAY *`.","Remove Quartz-only tokens (`L`, `W`, `?`, `#`, seconds field) and stray punctuation; check the offending field named in the message (`minute`, `hour`, `day-of-month`, `month`, `day-of-week`).","Note that day-of-week accepts 0-7 (both 0 and 7 mean Sunday) and month names/numbers are 1-12."],"exampleFix":"# before\nRRULE:FREQ=CRON;EXPR=0 9 ? * MONDAY *\n# after\nRRULE:FREQ=CRON;EXPR=0 9 * * MON-FRI","handlingStrategy":"validation","validationCode":"// Validate a cron atom before storing the automation schedule.\nfn valid_cron_atom(raw: &str, min: u32, max: u32, names: &[(&str, u32)]) -> bool {\n    let needle = raw.trim().to_ascii_uppercase();\n    if names.iter().any(|(n, _)| *n == needle) {\n        return true;\n    }\n    match raw.trim().parse::<u32>() {\n        Ok(v) => (min..=max).contains(&v),\n        Err(_) => false,\n    }\n}\nconst MONTHS: &[(&str, u32)] = &[(\"JAN\",1),(\"FEB\",2),(\"MAR\",3),(\"APR\",4),(\"MAY\",5),(\"JUN\",6),(\"JUL\",7),(\"AUG\",8),(\"SEP\",9),(\"OCT\",10),(\"NOV\",11),(\"DEC\",12)];\nconst WEEKDAYS: &[(&str, u32)] = &[(\"SUN\",0),(\"MON\",1),(\"TUE\",2),(\"WED\",3),(\"THU\",4),(\"FRI\",5),(\"SAT\",6)];","typeGuard":"fn is_valid_cron_expr(expr: &str) -> bool {\n    let fields: Vec<&str> = expr.split_whitespace().collect();\n    fields.len() == 5\n        && CronField::parse(fields[0], 0, 59, CronNameMap::none(), \"minute\").is_ok()\n        && CronField::parse(fields[1], 0, 23, CronNameMap::none(), \"hour\").is_ok()\n        && CronField::parse(fields[2], 1, 31, CronNameMap::none(), \"day-of-month\").is_ok()\n        && CronField::parse(fields[3], 1, 12, CronNameMap::month(), \"month\").is_ok()\n        && CronField::parse(fields[4], 0, 7, CronNameMap::weekday(), \"day-of-week\").is_ok()\n}","tryCatchPattern":null,"preventionTips":["Validate the CRON EXPR in the UI/script before saving the automation task so the user gets field-level feedback.","Lint pasted cron strings for Quartz-only tokens (L, W, ?, #) and a 6th seconds field.","Offer a cron preview/next-run computation at input time — it forces full parsing early."],"tags":["cron","automation","validation","parsing","schedule"],"backgroundTag":null,"analyzedSha":"8880682c63083a91624de936797efa3ce9e498fd","analyzedAt":"2026-08-16T11:31:27.956Z","schemaVersion":2},"datasetVersion":"2026-08-16T13:17:31.715Z"}