nikivdev/code · warning
failed to build midnight time
Error message
failed to build midnight time
What it means
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.
Source
Thrown at src/ssh_keys.rs:521
};
let content = serde_json::to_string_pretty(&entry)?;
fs::write(&path, content)?;
Ok(())
}
fn unlock_expires_at(entry: &SshKeyUnlock) -> Option<DateTime<Utc>> {
DateTime::<Utc>::from_timestamp(entry.expires_at, 0)
}
fn next_local_midnight_utc() -> Result<DateTime<Utc>> {
let now = Local::now();
let tomorrow = now
.date_naive()
.succ_opt()
.ok_or_else(|| anyhow::anyhow!("failed to calculate next day"))?;
let naive = tomorrow
.and_hms_opt(0, 0, 0)
.ok_or_else(|| anyhow::anyhow!("failed to build midnight time"))?;
let local_dt = Local
.from_local_datetime(&naive)
.single()
.or_else(|| Local.from_local_datetime(&naive).earliest())
.ok_or_else(|| anyhow::anyhow!("failed to resolve local midnight"))?;
Ok(local_dt.with_timezone(&Utc))
}
fn prompt_touch_id() -> Result<()> {
if !cfg!(target_os = "macos") {
bail!("Touch ID is not available on this OS");
}
if std::env::var("FLOW_NO_TOUCH_ID").is_ok() || !std::io::stdin().is_terminal() {
bail!("Touch ID prompt requires an interactive terminal");
}
let reason = "Flow needs Touch ID to unlock SSH keys.";
let reason = reason.replace('\\', "\\\\").replace('"', "\\\"");View on GitHub (pinned to a747e741ae)
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
Example fix
// before
.and_hms_opt(0, 0, 0)
.ok_or_else(|| anyhow::anyhow!("failed to build midnight time"))?
// after
.and_hms_opt(0, 0, 0)
.expect("midnight (00:00:00) is always a valid time") Defensive patterns
Strategy: validation
Validate before calling
let naive = chrono::Local::now().date_naive().succ_opt().map(|d| d.and_hms_opt(0, 0, 0)).flatten();
if naive.is_none() { eprintln!("cannot compute midnight; check clock/date"); } Try / catch
match unlock_ssh_key() {
Ok(v) => v,
Err(e) if e.to_string().contains("failed to build midnight time") => {
// unreachable defensive branch; log and fall back to now + 24h
eprintln!("midnight computation failed, defaulting to +24h");
fallback_expiry()
}
Err(e) => return Err(e),
} Prevention
- 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
When it happens
Trigger: 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.
Common situations: Not encountered in real deployments; would only appear from a code change passing non-constant values to and_hms_opt.
Related errors
- failed to calculate next day
- failed to resolve local midnight
- failed to capture stdout
- failed to capture stderr
AI-assisted analysis of nikivdev/code@a747e741ae (2026-09-01).
Data as JSON: /api/errors/4fc788a9a993bcd0.
Report an issue: GitHub.