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

  1. Treat as unreachable defensive code; no user action needed
  2. If it ever fires, verify the chrono version and system clock
  3. 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

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


AI-assisted analysis of nikivdev/code@a747e741ae (2026-09-01). Data as JSON: /api/errors/4fc788a9a993bcd0. Report an issue: GitHub.