{"record":{"id":"c9fff1ce3361f106","repo":"Hmbown/CodeWhale","slug":"cron-field-name-field-must-not-be-empty","errorCode":null,"errorMessage":"CRON {field_name} field must not be empty","messagePattern":"CRON (.+?) field must not be empty","errorType":"validation","errorClass":"anyhow::Error","httpStatus":null,"severity":"error","filePath":"crates/tui/src/automation_manager.rs","lineNumber":723,"sourceCode":"        if valid {\n            Ok(())\n        } else {\n            bail!(\"CRON EXPR day-of-month/month combination can never occur\")\n        }\n    }\n}\n\n#[derive(Debug, Clone)]\nstruct CronField {\n    values: Vec<u32>,\n    is_wildcard: bool,\n}\n\nimpl CronField {\n    fn parse(raw: &str, min: u32, max: u32, names: CronNameMap, field_name: &str) -> Result<Self> {\n        let trimmed = raw.trim();\n        if trimmed.is_empty() {\n            bail!(\"CRON {field_name} field must not be empty\");\n        }\n        let mut values = Vec::new();\n        let is_wildcard = trimmed == \"*\";\n        for part in trimmed.split(',') {\n            let part = part.trim();\n            if part.is_empty() {\n                bail!(\"CRON {field_name} field contains an empty list item\");\n            }\n            let (base, step) = if let Some((base, step)) = part.split_once('/') {\n                let step = step\n                    .trim()\n                    .parse::<u32>()\n                    .with_context(|| format!(\"Failed to parse CRON {field_name} step\"))?;\n                if step == 0 {\n                    bail!(\"CRON {field_name} step must be >= 1\");\n                }\n                (base.trim(), step)\n            } else {","sourceCodeStart":705,"sourceCodeEnd":741,"githubUrl":"https://github.com/Hmbown/CodeWhale/blob/0c42157ee52f9d55af2b506d71b46249910f77d3/crates/tui/src/automation_manager.rs#L705-L741","documentation":"CronField::parse bails when a whole field trims to the empty string. Because ParsedCronExpr::parse splits EXPR with split_whitespace, fields can never be empty on the public path; the guard exists for direct CronField::parse calls (tests, internal callers) with '' or whitespace-only input.","triggerScenarios":"Only reachable by invoking CronField::parse directly with an empty or whitespace-only field string; the public rrule/EXPR path cannot produce an empty field after whitespace splitting.","commonSituations":"Internal tests or future refactors calling CronField::parse directly; not a user-facing failure mode.","solutions":["Treat as an internal invariant: check for empty fields before calling CronField::parse","Route all expressions through ParsedCronExpr::parse or parse_rrule","Report a bug if this surfaces from a public API entry point"],"exampleFix":null,"handlingStrategy":"validation","validationCode":"fn has_no_empty_cron_field(expr: &str) -> bool {\n    expr.split_whitespace().all(|f| !f.trim().is_empty())\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Use parse_rrule as the single entry point for EXPR validation","Never hand untrimmed fields to CronField::parse directly","Treat this error as an internal invariant violation and report it upstream"],"tags":["rust","cron","validation","internal"],"backgroundTag":"cron-empty-field","analyzedSha":"0c42157ee52f9d55af2b506d71b46249910f77d3","analyzedAt":"2026-08-20T21:50:45.477Z","schemaVersion":2},"datasetVersion":"2026-08-21T23:17:16.201Z"}