{"record":{"id":"31ef310dc4eddba1","repo":"nautechsystems/nautilus_trader","slug":"price-precision-precision-exceeds-maximum-max-d","errorCode":null,"errorMessage":"price precision {precision} exceeds maximum {MAX_DECIMALS}","messagePattern":"price precision (.+?) exceeds maximum (.+?)","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"crates/adapters/lighter/src/common/parse.rs","lineNumber":92,"sourceCode":"    anyhow::ensure!(\n        decimals <= MAX_DECIMALS,\n        \"size decimals {decimals} exceeds maximum {MAX_DECIMALS}\",\n    );\n    anyhow::ensure!(ticks >= 0, \"negative tick count {ticks} for Quantity\");\n    let decimal = Decimal::new(ticks, u32::from(decimals));\n    Quantity::from_decimal_dp(decimal, decimals).map_err(|e| {\n        anyhow::anyhow!(\"Quantity overflow for ticks={ticks}, decimals={decimals}: {e}\")\n    })\n}\n\n/// Converts a decimal string into a Nautilus [`Price`] at the requested precision.\n///\n/// # Errors\n///\n/// Returns an error if the string is not a decimal, if `precision` exceeds\n/// [`MAX_DECIMALS`], or if the resulting value is out of range.\npub fn parse_price(value: &str, precision: u8) -> anyhow::Result<Price> {\n    anyhow::ensure!(\n        precision <= MAX_DECIMALS,\n        \"price precision {precision} exceeds maximum {MAX_DECIMALS}\",\n    );\n    let decimal =\n        Decimal::from_str(value).map_err(|e| anyhow::anyhow!(\"invalid price `{value}`: {e}\"))?;\n    Price::from_decimal_dp(decimal, precision)\n        .map_err(|e| anyhow::anyhow!(\"invalid price `{value}` at precision {precision}: {e}\"))\n}\n\n/// Converts a decimal string into a non-negative Nautilus [`Quantity`].\n///\n/// Zero is allowed because Lighter sends zero-size book levels to delete\n/// existing orders.\n///\n/// # Errors\n///\n/// Returns an error if the string is not a decimal, if `precision` exceeds\n/// [`MAX_DECIMALS`], if the value is negative, or if the resulting quantity","sourceCodeStart":74,"sourceCodeEnd":110,"githubUrl":"https://github.com/nautechsystems/nautilus_trader/blob/18893faf8b356be3320add8de2f861b0b647cf06/crates/adapters/lighter/src/common/parse.rs#L74-L110","documentation":"parse_price converts a decimal string into a Nautilus Price at a requested precision. Nautilus Price is fixed-precision and supports at most MAX_DECIMALS (FIXED_PRECISION, 16/18 depending on build) decimal places. The library rejects any precision argument above that maximum before attempting conversion, because such a precision cannot be represented.","triggerScenarios":"Calling parse_price with a precision argument greater than MAX_DECIMALS — e.g. hard-coding precision=18 or 20, or passing an unvalidated price_decimals value from a payload where the market reports more decimals than Nautilus supports.","commonSituations":"Copy-pasting precision from a different market or venue spec; a Lighter market with unusually high price_decimals in orderBookDetails; confusion between Lighter's decimal count and Nautilus's fixed-precision exponent.","solutions":["Check the market's price_decimals in the orderBookDetails response and clamp or reject markets whose precision exceeds MAX_DECIMALS before calling parse_price.","Pass the precision straight from the parsed market metadata instead of a hard-coded literal.","Cap the precision with `precision.min(MAX_DECIMALS)` only if rounding to fewer decimals is acceptable for your use case (note it may reject valid tick alignment otherwise).","Skip instruments whose precision is unsupported — Nautilus cannot represent them."],"exampleFix":"// before\nlet price = parse_price(raw, market.price_decimals)?;\n// after\nanyhow::ensure!(market.price_decimals <= MAX_DECIMALS, \"unsupported market precision\");\nlet price = parse_price(raw, market.price_decimals)?;","handlingStrategy":"validation","validationCode":"fn precision_supported(precision: u8) -> bool {\n    precision <= MAX_DECIMALS\n}","typeGuard":null,"tryCatchPattern":"match parse_price(raw, precision) {\n    Ok(p) => p,\n    Err(e) if e.to_string().contains(\"exceeds maximum\") => {\n        tracing::error!(\"market precision {precision} unsupported; skipping instrument\");\n        return Ok(None);\n    }\n    Err(e) => return Err(e.into()),\n}","preventionTips":["Validate price_decimals from orderBookDetails once at instrument load, not per message","Never hard-code precision literals; always take them from parsed market metadata","Skip instruments whose precision exceeds MAX_DECIMALS instead of clamping (clamping misaligns ticks)","Keep a subscription-time check so bad markets fail fast, not mid-stream"],"tags":["rust","parsing","validation","price","precision"],"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-14T05:17:10.506Z"}