{"record":{"id":"f121fac3b91bb871","repo":"Hmbown/CodeWhale","slug":"hourly-schedule-exceeded-its-range","errorCode":null,"errorMessage":"HOURLY schedule exceeded its range","messagePattern":"HOURLY schedule exceeded its range","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"warning","filePath":"crates/tui/src/automation_manager.rs","lineNumber":454,"sourceCode":"                    let anchor_naive = local_anchor_reference\n                        .date_naive()\n                        .and_hms_opt(hour, minute, 0)\n                        .ok_or_else(|| anyhow::anyhow!(\"Unable to construct HOURLY anchor\"))?;\n                    let interval_seconds = i64::from(*interval_hours) * 60 * 60;\n                    let elapsed_seconds = local_after\n                        .naive_local()\n                        .signed_duration_since(anchor_naive)\n                        .num_seconds();\n                    let mut steps = if elapsed_seconds < 0 {\n                        0\n                    } else {\n                        elapsed_seconds / interval_seconds + 1\n                    };\n\n                    for _ in 0..MAX_HOURLY_SEARCH_STEPS {\n                        let hours = i64::from(*interval_hours)\n                            .checked_mul(steps)\n                            .ok_or_else(|| anyhow::anyhow!(\"HOURLY schedule exceeded its range\"))?;\n                        let delta = Duration::try_hours(hours)\n                            .ok_or_else(|| anyhow::anyhow!(\"HOURLY schedule exceeded its range\"))?;\n                        let candidate_naive = anchor_naive\n                            .checked_add_signed(delta)\n                            .ok_or_else(|| anyhow::anyhow!(\"HOURLY schedule exceeded its range\"))?;\n\n                        if byday\n                            .as_ref()\n                            .is_none_or(|days| days.contains(&candidate_naive.weekday()))\n                            && let Some(candidate) =\n                                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","sourceCodeStart":436,"sourceCodeEnd":472,"githubUrl":"https://github.com/Hmbown/CodeWhale/blob/8880682c63083a91624de936797efa3ce9e498fd/crates/tui/src/automation_manager.rs#L436-L472","documentation":"Computing the next anchored HOURLY run multiplies INTERVAL (hours) by a step count with i64::checked_mul; this error means that multiplication overflowed, i.e. the schedule's anchor/elapsed arithmetic left the i64 range. It is a defensive guard: values produced by validated configs cannot plausibly reach it.","triggerScenarios":"A corrupted or hand-edited stored automation with an absurd INTERVAL, or an anchor positioned so the elapsed-seconds step count times INTERVAL exceeds i64; reached only via records that skipped parse-time validation.","commonSituations":"Hand-edited automation store entries; data corruption; records written by a buggy older version.","solutions":["Sanity-check INTERVAL (e.g. 1..=8760) before saving or scheduling the automation","Re-create the automation with a sane INTERVAL via the supported tooling","If the record was produced by current tooling, report it: this overflow should be unreachable"],"exampleFix":"// before\n\"FREQ=HOURLY;INTERVAL=4000000000\" // corrupted stored record\n// after\n\"FREQ=HOURLY;INTERVAL=24\"","handlingStrategy":"validation","validationCode":"let interval: u32 = parts.get(\"INTERVAL\").copied().unwrap_or(\"1\").parse()?;\nensure!((1..=8760).contains(&interval), \"INTERVAL must be between 1 and 8760 hours\");","typeGuard":"fn hourly_interval_is_sane(rrule: &str) -> bool {\n    rrule\n        .split(';')\n        .find_map(|kv| kv.split_once('=').filter(|(k, _)| k == \"INTERVAL\").map(|(_, v)| v))\n        .and_then(|v| v.parse::<u32>().ok())\n        .is_none_or(|i| (1..=8760).contains(&i))\n}","tryCatchPattern":null,"preventionTips":["Bound INTERVAL to a realistic range at every write path (tool input, API, import)","Do not hand-edit stored automation records; recreate via the supported tooling","Log the offending rrule whenever an overflow guard trips so corrupted records are findable","Remember these checked guards are tripwires for corrupted data, not expected errors"],"tags":["automation","rrule","scheduler","overflow","defensive"],"backgroundTag":null,"analyzedSha":"8880682c63083a91624de936797efa3ce9e498fd","analyzedAt":"2026-08-16T11:31:27.956Z","schemaVersion":2},"datasetVersion":"2026-08-16T13:17:31.715Z"}