vectordotdev/vector · error

max_future_ms validated to fit in i64 in Aggregate::new

Error message

max_future_ms validated to fit in i64 in Aggregate::new

What it means

`record_event_time` converts `event_time.max_future_ms` (u64) to i64 and expects it to fit, claiming validation in `Aggregate::new`. If `max_future_ms` exceeds `i64::MAX`, `try_from` fails and the process panics per-event. The expect encodes an invariant established at construction time.

Solutions

  1. Set `max_future_ms` to a sane value below i64::MAX (e.g. milliseconds-hours/days)
  2. Ensure `Aggregate::new` validates and rejects over-large `max_future_ms` at config load
  3. Run `vector validate` on the config to reject the value before runtime
  4. File a bug if a within-limits config still triggers the panic
Defensive patterns

Strategy: validation

Validate before calling

// reject oversized max_future_ms before building
if cfg.event_time.max_future_ms > i64::MAX as u64 {
    return Err("max_future_ms too large".into());
}

Prevention

When it happens

Trigger: An `Aggregate` constructed without validating `max_future_ms <= i64::MAX` (or a config value above i64::MAX reaching record_event_time), then processing a metric event with `max_future_ms > 0`.

Common situations: Extremely large `max_future_ms` values in config (e.g. hand-written huge numbers) bypassing the constructor validation in a fork or older version.

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


AI-assisted analysis of vectordotdev/vector@bdb87aeaa4 (2026-09-16). Data as JSON: /api/errors/72f8140c9bbc3d1b. Report an issue: GitHub.

Appendix: source

Thrown at src/transforms/aggregate/event_time.rs:72

        let ts = match timestamp {
            Some(ts) => ts,
            None => match event_time.missing_timestamp {
                MissingTimestamp::UseSystemTime => now,
                MissingTimestamp::Drop => {
                    emit!(AggregateEventDropped {
                        reason: "Event missing timestamp required for event-time aggregation."
                    });
                    return None;
                }
            },
        };
        // Preserve (or synthesize) the timestamp in the stored metric so that
        // event-time "latest" selection can compare timestamps reliably.
        data.time.timestamp = Some(ts);

        if event_time.max_future_ms > 0 {
            let max_future_ms = i64::try_from(event_time.max_future_ms)
                .expect("max_future_ms validated to fit in i64 in Aggregate::new");
            let drift_ms = ts.timestamp_millis().saturating_sub(now_ms);
            if drift_ms > max_future_ms {
                emit!(AggregateEventDropped {
                    reason: "Event timestamp too far in the future."
                });
                return None;
            }
        }

        let bucket_key = self.bucket_key(ts);

        if self.was_bucket_flushed(bucket_key) {
            emit!(AggregateEventDropped {
                reason: "Event timestamp is too late; bucket already flushed."
            });
            return None;
        }

View on GitHub (pinned to bdb87aeaa4)