{"record":{"id":"c217538dcdf4fe7d","repo":"Hmbown/CodeWhale","slug":"unable-to-round-cron-search-start","errorCode":null,"errorMessage":"Unable to round CRON search start","messagePattern":"Unable to round CRON search start","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"warning","filePath":"crates/tui/src/automation_manager.rs","lineNumber":525,"sourceCode":"                    }\n                    let Some(candidate_naive) = date.and_hms_opt(*byhour, *byminute, 0) else {\n                        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            }","sourceCodeStart":507,"sourceCodeEnd":543,"githubUrl":"https://github.com/Hmbown/CodeWhale/blob/8880682c63083a91624de936797efa3ce9e498fd/crates/tui/src/automation_manager.rs#L507-L543","documentation":"Before scanning for the next CRON match, the scheduler truncates the local start time to the minute via with_second(0).and_then(|dt| dt.with_nanosecond(0)). chrono's in-place setters return None only when the existing value is out of range — in practice a leap-second internal representation where the nanosecond field is >= 1_000_000_000 and cannot be truncated in place. A defensive, near-unreachable branch.","triggerScenarios":"local_after carrying a leap-second-style NaiveDateTime (nanosecond component beyond normal range, as produced by some clock sources at a leap second) at the moment a CRON schedule computes its next run.","commonSituations":"Essentially none: requires an exotic system clock producing leap-second timestamps while a CRON automation is scheduled.","solutions":["Not actionable on the caller side; treat it as an internal invariant failure and report it upstream with the schedule and system clock details","Recomputing from a fresh clock reading on the next scheduler tick usually clears it","If you control the clock source, feed truncated (non-leap-second) timestamps"],"exampleFix":null,"handlingStrategy":"fallback","validationCode":"let now_local = chrono::Local::now().naive_local();\nif now_local.nanosecond() >= 1_000_000_000 {\n    // leap-second representation: re-derive from truncated UTC\n    now_local = chrono::Utc::now().trunc_subsecs(0).with_timezone(&chrono::Local).naive_local();\n}","typeGuard":null,"tryCatchPattern":"match schedule.next_run(after) {\n    Ok(next) => Some(next),\n    Err(err) if err.to_string() == \"Unable to round CRON search start\" => {\n        log::warn!(\"leap-second clock value; retrying CRON scheduling next tick\");\n        None // retry on the next scheduler tick with a fresh clock reading\n    }\n    Err(err) => return Err(err),\n}","preventionTips":["Normalize clock inputs by truncating sub-second precision before scheduling","If you feed persisted timestamps into the scheduler, store already-truncated values","Report recurrences upstream — this branch is effectively an invariant violation"],"tags":["automation","cron","chrono","defensive"],"backgroundTag":null,"analyzedSha":"8880682c63083a91624de936797efa3ce9e498fd","analyzedAt":"2026-08-16T11:31:27.956Z","schemaVersion":2},"datasetVersion":"2026-08-16T13:17:31.715Z"}