{"record":{"id":"f3aa1b8fdea702d6","repo":"Hmbown/CodeWhale","slug":"cron-schedule-exceeded-its-range","errorCode":null,"errorMessage":"CRON schedule exceeded its range","messagePattern":"CRON schedule exceeded its range","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"warning","filePath":"crates/tui/src/automation_manager.rs","lineNumber":527,"sourceCode":"                        continue;\n                    };\n                    if let Some(candidate) = resolve_local_datetime(timezone, candidate_naive)\n                        && candidate.with_timezone(&Utc) > after\n                    {\n                        return Ok(candidate.with_timezone(&Utc));\n                    }\n                }\n                bail!(\"Unable to compute next WEEKLY run\");\n            }\n            Self::Cron { expr } => {\n                let cron = ParsedCronExpr::parse(expr)?;\n                let mut candidate_naive = local_after\n                    .naive_local()\n                    .with_second(0)\n                    .and_then(|dt| dt.with_nanosecond(0))\n                    .ok_or_else(|| anyhow::anyhow!(\"Unable to round CRON search start\"))?\n                    .checked_add_signed(Duration::minutes(1))\n                    .ok_or_else(|| anyhow::anyhow!(\"CRON schedule exceeded its range\"))?;\n\n                for _ in 0..MAX_CRON_SEARCH_MINUTES {\n                    if cron.matches(candidate_naive)\n                        && let Some(candidate) = resolve_local_datetime(timezone, candidate_naive)\n                    {\n                        let candidate = candidate.with_timezone(&Utc);\n                        if candidate > after {\n                            return Ok(candidate);\n                        }\n                    }\n                    candidate_naive = candidate_naive\n                        .checked_add_signed(Duration::minutes(1))\n                        .ok_or_else(|| anyhow::anyhow!(\"CRON schedule exceeded its range\"))?;\n                }\n                bail!(\"Unable to compute next CRON run within 5 years\");\n            }\n        }\n    }","sourceCodeStart":509,"sourceCodeEnd":545,"githubUrl":"https://github.com/Hmbown/CodeWhale/blob/8880682c63083a91624de936797efa3ce9e498fd/crates/tui/src/automation_manager.rs#L509-L545","documentation":"After rounding the CRON search start to the minute, the first candidate is produced with checked_add_signed(Duration::minutes(1)); None means the start time sits so close to chrono's NaiveDateTime boundary (roughly year +/-262143) that adding one minute overflows. Defensive guard against a system clock or stored 'after' time at the edge of the representable calendar.","triggerScenarios":"A CRON automation evaluated when local_after (now, or a persisted next-run value) is at or beyond the chrono datetime range — e.g. a corrupted stored slot or a misconfigured system clock set to an extreme year.","commonSituations":"Corrupted automation records with extreme datetimes; broken RTC/clock skew to absurd dates; not reachable with a sane clock.","solutions":["Check and correct the system clock if it shows an extreme date","Re-create the automation so its stored slot is recomputed from the real clock","Validate persisted slot values are within a sane range before loading"],"exampleFix":null,"handlingStrategy":"validation","validationCode":"let year = chrono::Local::now().year();\nensure!((1970..=9999).contains(&year), \"system clock year {year} is not usable for scheduling\");","typeGuard":"fn datetime_in_sane_range(dt: chrono::DateTime<chrono::Utc>) -> bool {\n    (1970..=9999).contains(&dt.year())\n}","tryCatchPattern":null,"preventionTips":["Validate the system clock at scheduler startup (NTP, sane year range)","Bounds-check persisted next-run slots when loading the automation store","Recreate automations after clock-corruption events instead of trusting stored slots"],"tags":["automation","cron","scheduler","overflow","chrono"],"backgroundTag":null,"analyzedSha":"8880682c63083a91624de936797efa3ce9e498fd","analyzedAt":"2026-08-16T11:31:27.956Z","schemaVersion":2},"datasetVersion":"2026-08-16T13:17:31.715Z"}