jdx/mise · error
elapsed timestamp delta must fit into u64
Error message
elapsed timestamp delta must fit into u64
What it means
mise panics with 'elapsed timestamp delta must fit into u64' in `elapsed_seconds_ceil` when the difference between two timestamps, rounded up to whole seconds, exceeds `u64::MAX` — i.e. roughly 584 billion years. The function computes nanosecond deltas between a reference `from` and `to` timestamp (used for `minimum_release_age` checks); since both come from a consistent process clock, this should be impossible and the expect marks it as an invariant.
Source
Thrown at src/duration.rs:21
use eyre::{Result, bail};
use jiff::{Span, Timestamp, Zoned, civil::date};
pub(crate) const HOURLY: Duration = Duration::from_secs(60 * 60);
pub(crate) const DAILY: Duration = Duration::from_secs(60 * 60 * 24);
pub(crate) const WEEKLY: Duration = Duration::from_secs(60 * 60 * 24 * 7);
/// Returns the number of whole seconds from `from` to `to`, rounded up.
///
/// Returns 0 when `from >= to` so callers don't have to guard against the
/// degenerate "cutoff is already in the future" case.
pub(crate) fn elapsed_seconds_ceil(from: Timestamp, to: Timestamp) -> u64 {
if from >= to {
return 0;
}
let nanos = to.as_nanosecond() - from.as_nanosecond();
u64::try_from((nanos + 999_999_999) / 1_000_000_000)
.expect("elapsed timestamp delta must fit into u64")
}
/// Returns a stable "now" timestamp for the lifetime of the process.
///
/// This is used for resolving relative durations (e.g. `minimum_release_age = "3d"`)
/// consistently: every resolution of the same relative duration within a single
/// mise invocation produces the same absolute timestamp, and downstream code
/// that converts the absolute timestamp back to a duration (e.g. for npm's
/// `--min-release-age`) gets the exact duration the user specified rather than
/// a slightly-larger value due to wall clock drift between phases.
pub(crate) fn process_now() -> Timestamp {
static PROCESS_NOW: OnceLock<Timestamp> = OnceLock::new();
*PROCESS_NOW.get_or_init(Timestamp::now)
}
pub(crate) fn parse_duration(s: &str) -> Result<Duration> {
match s.parse::<Span>() {
Ok(span) => {View on GitHub (pinned to afd2eddd3a)
Solutions
- Verify both timestamps use the same epoch and are produced by `stable_now`/the intended clock
- Clamp or validate the resolved release-age timestamp before computing the delta
- Return a saturating value (`u64::MAX`) or an error instead of panicking if extreme durations are possible
- Check for a typo'd duration unit in `minimum_release_age` config producing an enormous timestamp
Example fix
// before
u64::try_from((nanos + 999_999_999) / 1_000_000_000)
.expect("elapsed timestamp delta must fit into u64")
// after
u64::try_from((nanos + 999_999_999) / 1_000_000_000)
.unwrap_or(u64::MAX) // saturate instead of panicking Defensive patterns
Strategy: validation
Validate before calling
if to.as_nanosecond() - from.as_nanosecond() > u64::MAX as i128 { return Err(...); } Type guard
fn fits_u64(n: i128) -> bool { (0..=u64::MAX as i128).contains(&n) } Prevention
- Source both timestamps from the same stable clock
- Validate resolved minimum_release_age durations are sane before use
- Prefer saturating conversion (unwrap_or(u64::MAX)) for time deltas
When it happens
Trigger: Calling `elapsed_seconds_ceil` with timestamps from inconsistent epochs or corrupted nanosecond values — e.g. a `Timestamp::as_nanosecond` implementation backed by a clock that can go negative or saturate, or callers like `build_transitive_release_age_args`/`aube_project_config` constructing `to` far in the future from a malformed duration.
Common situations: A misconfigured or absurd `minimum_release_age` duration (e.g. a huge relative value) resolved into a far-future timestamp; clock changes or fake/test clocks with negative or extreme values; a change of the timestamp representation widening/narrowing types.
Understand the failure class
Background: "value must be between 0 and 1" / "out of range" / "must not be negative" errors: fixing range-validation failures across open-source libraries — this error's family across 42 libraries.
Related errors
- Unknown shim mode
- relay duration is too large
- GitHub API URL should be valid
- GitHub API URL should support path segments
- configured notifications came from managed files
AI-assisted analysis of jdx/mise@afd2eddd3a (2026-09-09).
Data as JSON: /api/errors/09f99b838b11a780.
Report an issue: GitHub.