nautechsystems/nautilus_trader · error
price decimals {decimals} exceeds maximum {MAX_DECIMALS}
Error message
price decimals {decimals} exceeds maximum {MAX_DECIMALS} What it means
`parse_price_from_ticks` converts an integer tick value and a decimal count into a Nautilus `Price`. It rejects any `decimals` value above `MAX_DECIMALS` (the precision limit `Price::from_mantissa_exponent` supports), because the resulting price precision would be unrepresentable.
Source
Thrown at crates/adapters/lighter/src/common/parse.rs:46
datetime::{NANOSECONDS_IN_MILLISECOND, NANOSECONDS_IN_SECOND},
};
use nautilus_model::types::{Price, Quantity, fixed::FIXED_PRECISION};
use rust_decimal::Decimal;
/// Maximum decimal places that fit into Nautilus [`Price`] / [`Quantity`].
pub const MAX_DECIMALS: u8 = FIXED_PRECISION;
/// Converts a Lighter price tick count into a Nautilus [`Price`].
///
/// Lighter encodes limit and trigger prices as `u32` multiples of `10^-decimals`
/// quote-asset units. The conversion uses pure integer arithmetic via
/// [`Price::from_mantissa_exponent`].
///
/// # Errors
///
/// Returns an error if `decimals` exceeds [`MAX_DECIMALS`].
pub fn parse_price_from_ticks(ticks: u32, decimals: u8) -> anyhow::Result<Price> {
anyhow::ensure!(
decimals <= MAX_DECIMALS,
"price decimals {decimals} exceeds maximum {MAX_DECIMALS}",
);
let exponent = -(decimals as i8);
Ok(Price::from_mantissa_exponent(
i64::from(ticks),
exponent,
decimals,
))
}
/// Converts a Lighter base-amount tick count into a Nautilus [`Quantity`].
///
/// Order sizes on the wire are signed `i64` multiples of `10^-decimals`
/// base-asset units. Nautilus [`Quantity`] is non-negative, so a negative
/// `ticks` value is rejected: callers (e.g. position parsers) extract the
/// sign separately before invoking this parser.
///View on GitHub (pinned to 18893faf8b)
Solutions
- Check the market's price precision and ensure it is <= MAX_DECIMALS before parsing.
- Round or scale the tick value to a supported precision if the source data has excess decimals.
- Inspect `MAX_DECIMALS` in crates/adapters/lighter/src/common/parse.rs to know the allowed limit.
Example fix
// before let price = parse_price_from_ticks(ticks, 20)?; // after let decimals = decimals.min(MAX_DECIMALS); let price = parse_price_from_ticks(ticks, decimals)?;
Defensive patterns
Strategy: validation
Validate before calling
if decimals > lighter::parse::MAX_DECIMALS {
decimals = lighter::parse::MAX_DECIMALS; // or reject the instrument
} Type guard
fn price_precision_supported(d: u8) -> bool { d <= lighter::parse::MAX_DECIMALS } Try / catch
let price = parse_price_from_ticks(ticks, decimals)
.map_err(|e| { eprintln!("price parse failed: {e}"); e })?; Prevention
- Check instrument price precision against MAX_DECIMALS when loading definitions.
- Reject or round instruments exceeding the precision limit at load time.
- Avoid hardcoding decimals copied from other venues.
When it happens
Trigger: Calling `parse_price_from_ticks(ticks, decimals)` with `decimals > MAX_DECIMALS`, e.g. when parsing an instrument definition whose price precision exceeds the adapter's maximum.
Common situations: Loading a Lighter instrument with unusually high price precision; misreading a market's quoted decimals field; hardcoding decimals from a different market.
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
- invalid {name} price: {e}
- size decimals {decimals} exceeds maximum {MAX_DECIMALS}
- price precision {precision} exceeds maximum {MAX_DECIMALS}
- {field} {value} is not exactly representable with price prec
- missing positive trigger_price for Binance algo order type {
AI-assisted analysis of nautechsystems/nautilus_trader@18893faf8b (2026-09-08).
Data as JSON: /api/errors/b315389ede9ed9c0.
Report an issue: GitHub.