nautechsystems/nautilus_trader · error · anyhow::Error
Verified inclusion timestamp exceeds nanoseconds
Error message
Verified inclusion timestamp exceeds nanoseconds
What it means
This library verifies a blockchain transaction inclusion by converting the inclusion block's timestamp (in seconds) into nanoseconds for the UnixNanos domain type. The checked_mul against NANOSECONDS_IN_SECOND fails when the seconds value would overflow the i64 nanoseconds range, so the library aborts rather than producing a corrupted timestamp.
Source
Thrown at crates/adapters/blockchain/src/execution/client.rs:4689
ts_event,
ts_event,
false,
false,
);
emitter.try_send_order_event(OrderEventAny::Rejected(rejected))
}
fn finalized_inclusion_time(included: &IncludedTransaction) -> anyhow::Result<UnixNanos> {
let inclusion = &included.finality.inclusion_header;
anyhow::ensure!(
inclusion.number == included.block_number
&& inclusion.hash == included.receipt.block_hash.to_string(),
"Verified inclusion header does not match the finalized receipt"
);
let timestamp = inclusion.timestamp;
let nanos = timestamp
.checked_mul(NANOSECONDS_IN_SECOND)
.ok_or_else(|| anyhow::anyhow!("Verified inclusion timestamp exceeds nanoseconds"))?;
Ok(UnixNanos::from(nanos))
}
fn execution_event_id(tx_hash: B256, event: &[u8]) -> UUID4 {
let mut identity = Vec::with_capacity(tx_hash.len() + event.len());
identity.extend_from_slice(tx_hash.as_slice());
identity.extend_from_slice(event);
let digest = keccak256(identity);
let mut bytes = [0u8; 16];
bytes.copy_from_slice(&digest[..16]);
UUID4::from_bytes(bytes)
}
struct FinalizedSwapFill {
venue_order_id: VenueOrderId,
trade_id: TradeId,
last_qty: Quantity,
last_px: Price,View on GitHub (pinned to 18893faf8b)
Solutions
- Verify the RPC node returns block.timestamp in seconds (hex-decoded) and not milliseconds; if in ms, divide by 1000 before this call
- Re-fetch the inclusion header from a trusted endpoint; a poisoned timestamp usually indicates a bad upstream response
- Check that NANOSECONDS_IN_SECOND and the arithmetic type width match the UnixNanos::from contract for your platform
- Clamp or validate timestamp <= i64::MAX / 1_000_000_000 before calling the verification API
Example fix
// before
let nanos = timestamp.checked_mul(NANOSECONDS_IN_SECOND)?;
// after
let timestamp_secs = if timestamp > 1_000_000_000_000 { timestamp / 1000 } else { timestamp };
let nanos = timestamp_secs.checked_mul(NANOSECONDS_IN_SECOND)?; Defensive patterns
Strategy: validation
Validate before calling
const MAX_TS_SECS: u64 = (i64::MAX as u64) / 1_000_000_000;
if inclusion.timestamp > MAX_TS_SECS {
return Err(anyhow!("timestamp {} too large for nanosecond conversion", inclusion.timestamp));
} Type guard
fn ts_in_nanos_range(ts: u64) -> bool { ts <= (i64::MAX as u64) / 1_000_000_000 } Try / catch
match timestamp.checked_mul(NANOSECONDS_IN_SECOND) {
Some(nanos) => Ok(UnixNanos::from(nanos)),
None => { log::error!("timestamp overflow: {}", timestamp); Err(...) }
} Prevention
- Assert header timestamps are in seconds at RPC response boundary
- Bound-check timestamps against a sane max (year 2100) before arithmetic
- Use checked arithmetic everywhere timestamps are scaled
- Pin and review RPC provider behavior on timestamp units
When it happens
Trigger: Calling the finalized-swap verification flow when inclusion.timestamp is an absurdly large value (e.g. corrupted RPC response, timestamp in milliseconds instead of seconds, or u64 max sentinel from a malicious/faulty node) so that timestamp * 1e9 exceeds the integer range.
Common situations: A misconfigured or buggy RPC provider returning timestamps already in milliseconds or nanoseconds; a mocked/fixture header with a placeholder timestamp; integer width differences after a dependency upgrade changing UnixNanos storage.
Understand the failure class
Background: "value must be between 0 and 1" / "out of range" / "must not be negative" errors: fixing range-validation failures across open-source libraries — this error's family across 42 libraries.
Related errors
- Finalized block timestamp overflows nanoseconds
- {type_name} raw value {raw} exceeds {raw_max_name}={raw_max}
- Derived minimum output is zero for quoted output {quoted_amo
- Binance {field} timestamp is outside the UnixNanos range: {v
- {type_name} amount {amount} overflows U256 while scaling fro
AI-assisted analysis of nautechsystems/nautilus_trader@18893faf8b (2026-09-08).
Data as JSON: /api/errors/daa7806ecb77d503.
Report an issue: GitHub.