{"record":{"id":"6b29a089b579a466","repo":"vectordotdev/vector","slug":"invalid-timestamp-6b29a0","errorCode":null,"errorMessage":"invalid timestamp","messagePattern":"invalid timestamp","errorType":"panic","errorClass":null,"httpStatus":null,"severity":"error","filePath":"lib/vector-core/src/event/proto.rs","lineNumber":224,"sourceCode":"\nimpl From<Metric> for super::Metric {\n    fn from(metric: Metric) -> Self {\n        let kind = match metric.kind() {\n            metric::Kind::Incremental => super::MetricKind::Incremental,\n            metric::Kind::Absolute => super::MetricKind::Absolute,\n        };\n\n        let name = metric.name;\n\n        let namespace = (!metric.namespace.is_empty()).then_some(metric.namespace);\n\n        // Sign can never be lost as ts.nanos is always non negative (per proto spec)\n        #[allow(clippy::cast_sign_loss)]\n        let timestamp = metric.timestamp.map(|ts| {\n            chrono::Utc\n                .timestamp_opt(ts.seconds, ts.nanos as u32)\n                .single()\n                .expect(\"invalid timestamp\")\n        });\n\n        let mut tags = MetricTags(\n            metric\n                .tags_v2\n                .into_iter()\n                .map(|(tag, values)| {\n                    (\n                        tag,\n                        values\n                            .values\n                            .into_iter()\n                            .map(|value| super::metric::TagValue::from(value.value))\n                            .collect(),\n                    )\n                })\n                .collect(),\n        );","sourceCodeStart":206,"sourceCodeEnd":242,"githubUrl":"https://github.com/vectordotdev/vector/blob/3708c39b12a93212ed8b8d7510b4cc7769cb5864/lib/vector-core/src/event/proto.rs#L206-L242","documentation":"While decoding a protobuf-encoded Metric (Vector's internal event proto), Vector converts ts.seconds/ts.nanos to a chrono DateTime with chrono::Utc.timestamp_opt(...).single().expect(\"invalid timestamp\") (lib/vector-core/src/event/proto.rs). timestamp_opt returns None when seconds/nanos are outside chrono's representable range (roughly years -262144..262143; nanos must be < 1e9), so a wildly out-of-range timestamp in the wire data panics the decoder.","triggerScenarios":"Decoding (from_proto) a Metric whose timestamp field carries seconds beyond chrono's range — e.g. a producer with a corrupted clock, multiplied epoch values (~year 60,000), i64::MAX, or nanos >= 1_000_000_000 — arriving over Vector-to-Vector gRPC (vector topology, internal_events proto) or from any emitter of Vector's event protobuf.","commonSituations":"Vector-to-Vector pipelines where an upstream host has a broken RTC/NTP or epoch-unit confusion (milliseconds vs seconds); hand-written producers of Vector's proto format; corrupted payloads after transport-level truncation; bugs in custom aggregators that synthesize metric timestamps.","solutions":["Fix the clock/timestamp source on the producing host (NTP sync); verify with date -u && timedatectl on the producer","Check for unit confusion upstream: milliseconds-since-epoch in a seconds field yields year ~55897 and panics the decoder","Sanitize timestamps at the producing boundary (clamp or drop metrics with |seconds| > ~8.2e15 / years outside 0000-9999) before sending","If you control the producer, ensure nanos stays within 0..999,999,999 as the proto spec requires"],"exampleFix":"// before\nlet timestamp = metric.timestamp.map(|ts| {\n    chrono::Utc.timestamp_opt(ts.seconds, ts.nanos as u32).single().expect(\"invalid timestamp\")\n});\n\n// after: reject instead of panic\nlet timestamp = metric.timestamp.and_then(|ts| {\n    chrono::Utc.timestamp_opt(ts.seconds, ts.nanos as u32).single()\n});","handlingStrategy":"validation","validationCode":"// Producer side: clamp/drop before serializing to proto\nfn sanitize_ts(seconds: i64, nanos: i32) -> Option<(i64, i32)> {\n    let within_range = chrono::DateTime::<chrono::Utc>::from_timestamp(seconds, nanos).is_some();\n    within_range.then_some((seconds, nanos))\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Verify producer clocks with NTP before shipping metrics cross-host","Keep epoch units as SECONDS in the seconds field; never milliseconds","On the consumer side, treat timestamp_opt(...).single() == None as 'drop field' rather than panic"],"tags":["vector","protobuf","chrono","timestamp","decode","panic"],"backgroundTag":"invalid-timestamp","analyzedSha":"3708c39b12a93212ed8b8d7510b4cc7769cb5864","analyzedAt":"2026-08-20T07:02:18.786Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-14T00:17:10.932Z"}