vectordotdev/vector · error
i64 -> f64 produced NaN
Error message
i64 -> f64 produced NaN
What it means
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.
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
Example fix
// before
NotNan::new(ts_millis as f64 / 1000.0).expect("i64 -> f64 produced NaN")
// after
let millis = ts_millis.clamp(-253_402_300_799_000, 253_402_300_799_000);
NotNan::new(millis as f64 / 1000.0).expect("i64 -> f64 produced NaN") Defensive patterns
Strategy: validation
Validate before calling
// clamp timestamps to a representable range before GELF conversion
fn ts_in_range(t: &chrono::DateTime<chrono::Utc>) -> bool {
let y = t.year();
(1..=9999).contains(&y)
} Prevention
- Sanitize timestamps from upstream sources before ingestion
- Clamp out-of-range epoch values
- Include the offending event when reporting bugs
When it happens
Trigger: 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.
Common situations: 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.
Understand the failure class
Background: "This is a bug, please report it": internal invariant violations, unreachable panics, and SNH errors explained — this error's family across 47 libraries.
Related errors
AI-assisted analysis of vectordotdev/vector@bdb87aeaa4 (2026-09-16).
Data as JSON: /api/errors/da3aa68eff103d1a.
Report an issue: GitHub.
Appendix: source
Thrown at lib/codecs/src/encoding/format/gelf.rs:212
match field.as_str() {
VERSION | HOST | SHORT_MESSAGE | FULL_MESSAGE | FACILITY | FILE => {
if !value.is_bytes() {
err_invalid_type(field, "UTF-8 string", value.kind_str())?;
}
}
TIMESTAMP => {
if !(value.is_timestamp() || value.is_integer()) {
err_invalid_type(field, "timestamp or integer", value.kind_str())?;
}
// convert a `Value::Timestamp` to a GELF specified timestamp where milliseconds are represented by the fractional part of a float.
if let Value::Timestamp(ts) = value {
let ts_millis = ts.timestamp_millis();
if ts_millis % 1000 != 0 {
// i64 to f64 / 1000.0 will never be NaN
*value = Value::Float(
NotNan::new(ts_millis as f64 / 1000.0)
.expect("i64 -> f64 produced NaN"),
);
} else {
// keep full range of representable time if no milliseconds are set
// but still convert to numeric according to GELF protocol
*value = Value::Integer(ts.timestamp())
}
}
}
LEVEL => {
if !value.is_integer() {
err_invalid_type(field, "integer", value.kind_str())?;
}
}
LINE => {
if !(value.is_float() || value.is_integer()) {
err_invalid_type(field, "number", value.kind_str())?;
}
}View on GitHub (pinned to bdb87aeaa4)