{"record":{"id":"800998755ab54c27","repo":"nautechsystems/nautilus_trader","slug":"second-timestamp-secs-overflows-when-scaled-to-n","errorCode":null,"errorMessage":"second timestamp {secs} overflows when scaled to nanoseconds","messagePattern":"second timestamp (.+?) overflows when scaled to nanoseconds","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"crates/adapters/lighter/src/common/parse.rs","lineNumber":197,"sourceCode":"///\n/// # Errors\n///\n/// Returns an error if `micros * 1_000` would overflow `u64`.\npub fn parse_micros_to_nanos(micros: u64) -> anyhow::Result<UnixNanos> {\n    let nanos = micros.checked_mul(1_000).ok_or_else(|| {\n        anyhow::anyhow!(\"microsecond timestamp {micros} overflows when scaled to nanoseconds\")\n    })?;\n    Ok(UnixNanos::from(nanos))\n}\n\n/// Converts a Unix second timestamp into [`UnixNanos`].\n///\n/// # Errors\n///\n/// Returns an error if `secs * 1_000_000_000` would overflow `u64`.\npub fn parse_secs_to_nanos(secs: u64) -> anyhow::Result<UnixNanos> {\n    let nanos = secs.checked_mul(NANOSECONDS_IN_SECOND).ok_or_else(|| {\n        anyhow::anyhow!(\"second timestamp {secs} overflows when scaled to nanoseconds\")\n    })?;\n    Ok(UnixNanos::from(nanos))\n}\n\n/// Converts a signed Unix millisecond timestamp into [`UnixNanos`].\n///\n/// Negative inputs are mapped to `Ok(None)` so callers can model fields\n/// where the wire uses `-1` (or any negative sentinel) as \"absent\". Fields\n/// that overload `0` with a separate meaning (e.g. `0` for IOC on\n/// `OrderInfo::order_expiry`) must apply that interpretation at the call\n/// site; this parser treats `0` as a literal Unix epoch timestamp.\n///\n/// # Errors\n///\n/// Returns an error if a non-negative `millis` overflows when scaled to\n/// nanoseconds.\npub fn parse_optional_millis_to_nanos(millis: i64) -> anyhow::Result<Option<UnixNanos>> {\n    if millis < 0 {","sourceCodeStart":179,"sourceCodeEnd":215,"githubUrl":"https://github.com/nautechsystems/nautilus_trader/blob/18893faf8b356be3320add8de2f861b0b647cf06/crates/adapters/lighter/src/common/parse.rs#L179-L215","documentation":"parse_secs_to_nanos converts a Unix-seconds timestamp to nanoseconds using secs.checked_mul(NANOSECONDS_IN_SECOND). If secs * 1_000_000_000 would overflow u64 (secs > ~18.4 billion, i.e. year ~2554), the error is raised to avoid silent wraparound in release builds.","triggerScenarios":"Calling parse_secs_to_nanos (directly, from parse_funding_rate_update, or from the parse_secs_to_nanos_rejects_overflow test) with a seconds value above ~1.844e10 — e.g. a corrupted funding-rate timestamp field or seconds passed as milliseconds.","commonSituations":"Passing a millisecond value where seconds are expected (1000x too large for normal dates is fine, but far-future/corrupt values overflow); malformed funding rate updates from the venue.","solutions":["Confirm the field is in seconds; if it is milliseconds use parse_millis_to_nanos instead.","Sanity-check the timestamp range (e.g. reject values outside a plausible window) before conversion.","Inspect the raw payload; treat overflowing values as malformed messages and drop them."],"exampleFix":"// before\nlet ts = parse_secs_to_nanos(millis_field)?; // field is milliseconds\n// after\nlet ts = parse_millis_to_nanos(millis_field)?;","handlingStrategy":"validation","validationCode":"fn secs_plausible(secs: u64) -> bool { (1_400_000_000..u64::MAX / 1_000_000_000).contains(&secs) }","typeGuard":"fn is_secs(v: u64) -> bool { (1_400_000_000..18_446_744_073).contains(&v) }","tryCatchPattern":"let ts = parse_secs_to_nanos(secs)\n    .map_err(|e| { warn!(\"funding ts overflow: {e}\"); e })?;","preventionTips":["Verify the funding-rate timestamp is in seconds; use parse_millis_to_nanos for ms fields","Reject timestamps outside a sane date window before conversion","Never pre-scale seconds to millis before calling this function"],"tags":["timestamp","overflow","parsing","lighter"],"backgroundTag":"value-out-of-range","analyzedSha":"18893faf8b356be3320add8de2f861b0b647cf06","analyzedAt":"2026-09-08T20:49:34.690Z","contentChangedAt":"2026-09-08T20:49:34.690Z","schemaVersion":2},"datasetVersion":"2026-09-14T00:17:10.932Z"}