nautechsystems/nautilus_trader · error
Failed to scale continuous-future adjustment to fixed precis
Error message
Failed to scale continuous-future adjustment to fixed precision
What it means
`BarBuilder::set_adjustment` converts a continuous-future adjustment `Price` from its own mantissa/scale into the builder's fixed `FIXED_PRECISION` via `mantissa_exponent_to_fixed_i128`. If the rescale would lose precision or overflow the i128 intermediate, the helper returns None and this `.expect` panics.
Source
Thrown at crates/data/src/aggregation.rs:228
/// # Panics
///
/// Panics if scaling the spread `adjustment` to the fixed-point representation overflows.
pub fn set_adjustment(&mut self, adjustment: Decimal, mode: ContinuousFutureAdjustmentType) {
if mode.is_ratio() {
self.adjustment_is_ratio = true;
self.adjustment_ratio = adjustment.to_f64().unwrap_or(1.0);
self.adjustment_active = adjustment != Decimal::ONE;
return;
}
// Spread mode: scale the Decimal offset to FIXED_PRECISION once so the hot path
// can add it straight onto `price.raw`. Signed PriceRaw supports negatives, so
// backward-spread offsets that push prices below zero remain representable.
self.adjustment_is_ratio = false;
let exponent = -(adjustment.scale() as i8);
let raw_i128 =
mantissa_exponent_to_fixed_i128(adjustment.mantissa(), exponent, FIXED_PRECISION)
.expect("Failed to scale continuous-future adjustment to fixed precision");
#[allow(
clippy::useless_conversion,
reason = "i128 to PriceRaw is real when not high-precision"
)]
let raw: PriceRaw = raw_i128
.try_into()
.expect("Continuous-future adjustment exceeds PriceRaw range");
self.adjustment_raw = raw;
self.adjustment_active = self.adjustment_raw != 0;
}
fn apply_adjustment_to_price(&self, price: Price) -> Price {
if !self.adjustment_active {
return price;
}
View on GitHub (pinned to 18893faf8b)
Solutions
- Round/quantize the adjustment Price to FIXED_PRECISION before passing it to `set_adjustment`
- Verify the adjustment mantissa comes from the instrument's price precision, not raw float parsing
- Clamp or re-scale the adjustment value at the data-provider boundary
- If larger precision is genuinely needed, this is a platform limitation — file/track a change to the fixed precision constant
Example fix
// before
builder.set_adjustment(adjustment_price); // panics if scale > FIXED_PRECISION
// after
let adj = Price::new(
adjustment_price.as_f64(),
FIXED_PRECISION as u8,
); // quantize to fixed precision first
builder.set_adjustment(adj); Defensive patterns
Strategy: validation
Validate before calling
// Rust: quantize the adjustment to the builder's fixed precision first let adj = Price::new(adjustment_f64, FIXED_PRECISION as u8); assert!(adjustment_f64.is_finite(), "adjustment must be finite");
Try / catch
let result = std::panic::catch_unwind(|| builder.set_adjustment(adj));
Prevention
- Always construct adjustment Prices at FIXED_PRECISION
- Reject provider data with more decimals than the platform precision
- Check mantissa scaling when converting floats to Price
When it happens
Trigger: Calling `set_adjustment` with a Price whose scale is finer than FIXED_PRECISION (e.g. an 11+ decimal-place price when fixed precision is 9) or whose mantissa is so large that scaling up overflows i128.
Common situations: Configuring spread adjustment factors parsed from CSV/JSON with unusual precision; instruments quoted with more decimals than the platform's fixed precision; hand-built test prices with extreme exponents.
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
- Continuous-future adjustment exceeds PriceRaw range
- DurationNanos overflow in from_micros
- {e}
- quantity for {currency} exceeds signed raw bounds
- quantity for {currency} overflowed while increasing raw scal
AI-assisted analysis of nautechsystems/nautilus_trader@18893faf8b (2026-09-08).
Data as JSON: /api/errors/3a569001c34a8484.
Report an issue: GitHub.