{"record":{"id":"4fc788a9a993bcd0","repo":"nikivdev/code","slug":"failed-to-build-midnight-time","errorCode":null,"errorMessage":"failed to build midnight time","messagePattern":"failed to build midnight time","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"warning","filePath":"src/ssh_keys.rs","lineNumber":521,"sourceCode":"    };\n    let content = serde_json::to_string_pretty(&entry)?;\n    fs::write(&path, content)?;\n    Ok(())\n}\n\nfn unlock_expires_at(entry: &SshKeyUnlock) -> Option<DateTime<Utc>> {\n    DateTime::<Utc>::from_timestamp(entry.expires_at, 0)\n}\n\nfn next_local_midnight_utc() -> Result<DateTime<Utc>> {\n    let now = Local::now();\n    let tomorrow = now\n        .date_naive()\n        .succ_opt()\n        .ok_or_else(|| anyhow::anyhow!(\"failed to calculate next day\"))?;\n    let naive = tomorrow\n        .and_hms_opt(0, 0, 0)\n        .ok_or_else(|| anyhow::anyhow!(\"failed to build midnight time\"))?;\n    let local_dt = Local\n        .from_local_datetime(&naive)\n        .single()\n        .or_else(|| Local.from_local_datetime(&naive).earliest())\n        .ok_or_else(|| anyhow::anyhow!(\"failed to resolve local midnight\"))?;\n    Ok(local_dt.with_timezone(&Utc))\n}\n\nfn prompt_touch_id() -> Result<()> {\n    if !cfg!(target_os = \"macos\") {\n        bail!(\"Touch ID is not available on this OS\");\n    }\n    if std::env::var(\"FLOW_NO_TOUCH_ID\").is_ok() || !std::io::stdin().is_terminal() {\n        bail!(\"Touch ID prompt requires an interactive terminal\");\n    }\n\n    let reason = \"Flow needs Touch ID to unlock SSH keys.\";\n    let reason = reason.replace('\\\\', \"\\\\\\\\\").replace('\"', \"\\\\\\\"\");","sourceCodeStart":503,"sourceCodeEnd":539,"githubUrl":"https://github.com/nikivdev/code/blob/a747e741ae92c09071d0ae946ab48488adcff1ce/src/ssh_keys.rs#L503-L539","documentation":"After computing tomorrow's date, next_local_midnight_utc builds a NaiveTime of 00:00:00 via and_hms_opt. This returns None only for out-of-range hour/min/sec values, which cannot happen with the constants (0,0,0), so the error is effectively a defensive guard that is unreachable in normal operation. It exists so the function returns Result instead of panicking if chrono semantics change.","triggerScenarios":"Calling and_hms_opt(0, 0, 0) returning None — theoretically only if the date value is invalid or chrono's API invariants break; no realistic runtime trigger with literal 0,0,0.","commonSituations":"Not encountered in real deployments; would only appear from a code change passing non-constant values to and_hms_opt.","solutions":["Treat as unreachable defensive code; no user action needed","If it ever fires, verify the chrono version and system clock","Refactor to use Time::MIN or with_hms(0,0,0) which cannot fail"],"exampleFix":"// before\n.and_hms_opt(0, 0, 0)\n.ok_or_else(|| anyhow::anyhow!(\"failed to build midnight time\"))?\n// after\n.and_hms_opt(0, 0, 0)\n.expect(\"midnight (00:00:00) is always a valid time\")","handlingStrategy":"validation","validationCode":"let naive = chrono::Local::now().date_naive().succ_opt().map(|d| d.and_hms_opt(0, 0, 0)).flatten();\nif naive.is_none() { eprintln!(\"cannot compute midnight; check clock/date\"); }","typeGuard":null,"tryCatchPattern":"match unlock_ssh_key() {\n    Ok(v) => v,\n    Err(e) if e.to_string().contains(\"failed to build midnight time\") => {\n        // unreachable defensive branch; log and fall back to now + 24h\n        eprintln!(\"midnight computation failed, defaulting to +24h\");\n        fallback_expiry()\n    }\n    Err(e) => return Err(e),\n}","preventionTips":["Do not pass dynamic values into and_hms_opt; keep (0,0,0) constant","Keep chrono updated","Treat this as a canary for clock corruption"],"tags":["chrono","datetime","defensive-code"],"backgroundTag":"date-calculation-failed","analyzedSha":"a747e741ae92c09071d0ae946ab48488adcff1ce","analyzedAt":"2026-09-01T22:43:55.719Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-08T10:18:20.063Z"}