{"record":{"id":"02bdf386c6d46edd","repo":"vectordotdev/vector","slug":"interval-ms-validated-to-fit-in-i64-in-aggregate-new","errorCode":null,"errorMessage":"interval_ms validated to fit in i64 in Aggregate::new","messagePattern":"interval_ms validated to fit in i64 in Aggregate::new","errorType":"panic","errorClass":null,"httpStatus":null,"severity":"error","filePath":"src/transforms/aggregate/event_time.rs","lineNumber":118,"sourceCode":"            \"only storable metrics reach event-time bucketing\"\n        );\n        self.record_into_bucket(bucket_key, series, data, metadata);\n        emit!(AggregateEventRecorded);\n        None\n    }\n\n    /// Start of the half-open window `[bucket_key, bucket_key + interval_ms)` containing\n    /// `timestamp`, aligned to multiples of `interval_ms` from the Unix epoch.\n    ///\n    /// Euclidean division (`div_euclid`) is required: Rust's truncating `/`\n    /// rounds toward zero, so timestamps just before the epoch (negative\n    /// millis) would incorrectly map into the non-negative bucket `[0, interval)`\n    /// instead of `[-interval, 0)`.\n    pub(crate) fn bucket_key(&self, timestamp: DateTime<Utc>) -> BucketKey {\n        let timestamp_ms = timestamp.timestamp_millis();\n        // Range-validated in `Aggregate::new` to fit in i64.\n        let interval_ms = i64::try_from(self.config.interval_ms)\n            .expect(\"interval_ms validated to fit in i64 in Aggregate::new\");\n        timestamp_ms\n            .div_euclid(interval_ms)\n            .saturating_mul(interval_ms)\n    }\n\n    /// Returns `true` if `bucket_key` belongs to a window that has already\n    /// been emitted and therefore must not accept any further events.\n    ///\n    /// `watermark` is the *exclusive end* of the highest bucket flushed so\n    /// far -- equivalently, the smallest `bucket_key` that is still valid to\n    /// record into. `allowed_lateness_ms` is honoured at flush time (it\n    /// delays closing the bucket); once a window has been emitted it is\n    /// closed unconditionally and late events for it are dropped.\n    const fn was_bucket_flushed(&self, bucket_key: BucketKey) -> bool {\n        if let Some(watermark) = self.watermark {\n            bucket_key < watermark\n        } else {\n            false","sourceCodeStart":100,"sourceCodeEnd":136,"githubUrl":"https://github.com/vectordotdev/vector/blob/bdb87aeaa4c4ff27c0ba643c1c77b21bf2ef4013/src/transforms/aggregate/event_time.rs#L100-L136","documentation":"`bucket_key` converts the configured `interval_ms` (u64) to i64 with `try_from` and expects success, relying on validation in `Aggregate::new`. A value above `i64::MAX` panics here. The conversion must be i64 because `div_euclid` operates on i64 timestamps.","triggerScenarios":"An Aggregate whose `interval_ms` exceeds `i64::MAX` reaches `bucket_key` (via `record_event_time`) without constructor validation.","commonSituations":"Absurdly large interval values in config on versions/forks lacking constructor validation; direct unit-test construction of Aggregate with unvalidated config.","solutions":["Use a realistic `interval_ms` (millisecond-scale window sizes)","Ensure `Aggregate::new` validates `interval_ms` fits in i64 and rejects the config otherwise","Run `vector validate` before deployment","File a bug if a reasonable interval triggers the panic"],"exampleFix":null,"handlingStrategy":"validation","validationCode":"if cfg.interval_ms > i64::MAX as u64 {\n    return Err(\"interval_ms too large\".into());\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Use realistic window intervals (seconds/minutes)","Validate interval fits i64 during config load","Add unit tests for extreme interval values","Run `vector validate` before deployment"],"tags":["rust","panic","integer-overflow","transforms"],"backgroundTag":"value-out-of-range","analyzedSha":"bdb87aeaa4c4ff27c0ba643c1c77b21bf2ef4013","analyzedAt":"2026-09-16T02:53:35.741Z","contentChangedAt":"2026-09-16T02:53:35.741Z","schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}