nautechsystems/nautilus_trader · error
Overflow when scaling f64 to fixed-point u128
Error message
Overflow when scaling f64 to fixed-point u128
What it means
f64_to_fixed_u128 converts a non-negative float to raw fixed-point u128, scaling by 10^(FIXED_PRECISION - precision). The checked_mul panics with this message when the scaled result exceeds u128::MAX — the widest fixed-point representation available.
Source
Thrown at crates/model/src/types/fixed.rs:947
/// # Panics
///
/// Panics if `precision` exceeds [`FIXED_PRECISION`], or if scaling the rounded value
/// overflows the raw integer range.
#[must_use]
#[expect(
clippy::cast_precision_loss,
clippy::cast_possible_truncation,
clippy::cast_sign_loss,
reason = "f64 to fixed-point conversion is inherently lossy; callers validate range and finiteness"
)]
pub fn f64_to_fixed_u128(value: f64, precision: u8) -> u128 {
check_fixed_precision(precision).expect_display(FAILED);
let pow1 = 10_u128.pow(u32::from(precision));
let pow2 = 10_u128.pow(u32::from(FIXED_PRECISION - precision));
let rounded = (value * pow1 as f64).round() as u128;
rounded
.checked_mul(pow2)
.expect("Overflow when scaling f64 to fixed-point u128")
}
/// Converts a raw fixed-point `i64` value back to an `f64` value.
#[must_use]
#[expect(
clippy::cast_precision_loss,
reason = "i64 to f64 is inherently lossy above 2^53; accepted for float interop"
)]
pub fn fixed_i64_to_f64(value: i64) -> f64 {
(value as f64) / FIXED_SCALAR
}
/// Converts a raw fixed-point `i128` value back to an `f64` value.
#[must_use]
#[expect(
clippy::cast_precision_loss,
reason = "i128 to f64 is inherently lossy above 2^53; accepted for float interop"
)]View on GitHub (pinned to 18893faf8b)
Solutions
- Validate value is finite, non-negative, and within u128 representable range before conversion.
- Fix unit scaling at the data source (divide by the unit factor) rather than widening further — u128 is the largest variant.
- Reject the value and surface a domain error instead of converting.
Example fix
// before
let raw = f64_to_fixed_u128(value, precision); // panics for huge values
// after
let max = u128::MAX as f64 / 10f64.powi(FIXED_PRECISION);
if !(value.is_finite() && (0.0..=max).contains(&value)) {
return Err(...);
}
let raw = f64_to_fixed_u128(value, precision); Defensive patterns
Strategy: validation
Validate before calling
const MAX: f64 = u128::MAX as f64 / 10f64.powi(FIXED_PRECISION); assert!(value.is_finite() && (0.0..=MAX).contains(&value)); let raw = f64_to_fixed_u128(value, precision);
Type guard
fn fits_u128_fixed(value: f64) -> bool {
value.is_finite() && (0.0..=u128::MAX as f64 / 10f64.powi(FIXED_PRECISION)).contains(&value)
} Prevention
- Fix unit scaling at the source (e.g. token wei vs whole units) — u128 is the widest available.
- Sanitize all external numeric data for finiteness and magnitude.
- Log and reject outliers instead of converting them.
When it happens
Trigger: Calling f64_to_fixed_u128 with values whose scaled magnitude exceeds u128::MAX (~3.4e38 at precision 0), typically only from unvalidated/huge float input or from casts of non-finite values saturating at the bound.
Common situations: Extreme synthetic values in tests (test_f64_to_fixed_u128_overflow_panics), data corruption producing astronomic magnitudes, or mis-scaled units (e.g. wei instead of ETH).
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
- Overflow when scaling f64 to fixed-point i64
- Overflow when scaling f64 to fixed-point i128
- Overflow when scaling f64 to fixed-point u64
- Fixed-point scale fits QuantityRaw
- Overflow occurred when multiplying `Quantity`
AI-assisted analysis of nautechsystems/nautilus_trader@18893faf8b (2026-09-08).
Data as JSON: /api/errors/d59e57687420f25f.
Report an issue: GitHub.