{"record":{"id":"da3aa68eff103d1a","repo":"vectordotdev/vector","slug":"i64-f64-produced-nan","errorCode":null,"errorMessage":"i64 -> f64 produced NaN","messagePattern":"i64 -> f64 produced NaN","errorType":"panic","errorClass":null,"httpStatus":null,"severity":"error","filePath":"lib/codecs/src/encoding/format/gelf.rs","lineNumber":212,"sourceCode":"            match field.as_str() {\n                VERSION | HOST | SHORT_MESSAGE | FULL_MESSAGE | FACILITY | FILE => {\n                    if !value.is_bytes() {\n                        err_invalid_type(field, \"UTF-8 string\", value.kind_str())?;\n                    }\n                }\n                TIMESTAMP => {\n                    if !(value.is_timestamp() || value.is_integer()) {\n                        err_invalid_type(field, \"timestamp or integer\", value.kind_str())?;\n                    }\n\n                    // convert a `Value::Timestamp` to a GELF specified timestamp where milliseconds are represented by the fractional part of a float.\n                    if let Value::Timestamp(ts) = value {\n                        let ts_millis = ts.timestamp_millis();\n                        if ts_millis % 1000 != 0 {\n                            // i64 to f64 / 1000.0 will never be NaN\n                            *value = Value::Float(\n                                NotNan::new(ts_millis as f64 / 1000.0)\n                                    .expect(\"i64 -> f64 produced NaN\"),\n                            );\n                        } else {\n                            // keep full range of representable time if no milliseconds are set\n                            // but still convert to numeric according to GELF protocol\n                            *value = Value::Integer(ts.timestamp())\n                        }\n                    }\n                }\n                LEVEL => {\n                    if !value.is_integer() {\n                        err_invalid_type(field, \"integer\", value.kind_str())?;\n                    }\n                }\n                LINE => {\n                    if !(value.is_float() || value.is_integer()) {\n                        err_invalid_type(field, \"number\", value.kind_str())?;\n                    }\n                }","sourceCodeStart":194,"sourceCodeEnd":230,"githubUrl":"https://github.com/vectordotdev/vector/blob/bdb87aeaa4c4ff27c0ba643c1c77b21bf2ef4013/lib/codecs/src/encoding/format/gelf.rs#L194-L230","documentation":"In GELF field coercion (`coerce_field_names_and_values`), timestamp values with sub-second milliseconds are converted via `ts_millis as f64 / 1000.0` and wrapped in `NotNan`. The `.expect` panics if the conversion produced NaN. The code comments note this division can never produce NaN for valid i64 inputs, so this is an internal invariant check against `ordered-float`'s NaN rejection.","triggerScenarios":"Converting a GELF event whose timestamp field is a `Value::Timestamp` with non-zero milliseconds, if the i64-to-f64 cast unexpectedly yields NaN — essentially only with extreme i64 values outside safe f64 precision, which still cannot be NaN.","commonSituations":"Practically unreachable; could only surface with corrupted timestamps (e.g. far out-of-range values from a malformed input source) or a compiler/platform float anomaly.","solutions":["Validate timestamps before ingestion (clamp to a sane range, e.g. within a few decades of now)","Check upstream sources for malformed epoch values that could overflow the cast","If reproducible, capture the event and report a bug with the timestamp value"],"exampleFix":"// before\nNotNan::new(ts_millis as f64 / 1000.0).expect(\"i64 -> f64 produced NaN\")\n// after\nlet millis = ts_millis.clamp(-253_402_300_799_000, 253_402_300_799_000);\nNotNan::new(millis as f64 / 1000.0).expect(\"i64 -> f64 produced NaN\")","handlingStrategy":"validation","validationCode":"// clamp timestamps to a representable range before GELF conversion\nfn ts_in_range(t: &chrono::DateTime<chrono::Utc>) -> bool {\n    let y = t.year();\n    (1..=9999).contains(&y)\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Sanitize timestamps from upstream sources before ingestion","Clamp out-of-range epoch values","Include the offending event when reporting bugs"],"tags":["panic","gelf","timestamp","float","notnan"],"backgroundTag":"internal-invariant-violation","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"}