{"record":{"id":"22b29b9d3adc8a53","repo":"nautechsystems/nautilus_trader","slug":"invalid-price-value-at-precision-precision","errorCode":null,"errorMessage":"invalid price `{value}` at precision {precision}: {e}","messagePattern":"invalid price `(.+?)` at precision (.+?): (.+?)","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"crates/adapters/lighter/src/websocket/parse.rs","lineNumber":1202,"sourceCode":"        return Ok(UnixNanos::default());\n    }\n\n    let millis = if timestamp <= UNIX_TIMESTAMP_SECONDS_MAX {\n        timestamp * 1_000\n    } else {\n        timestamp\n    };\n\n    parse_millis_to_nanos(millis as u64)\n}\n\nfn parse_optional_price(value: Decimal, precision: u8) -> anyhow::Result<Option<Price>> {\n    if value.is_zero() {\n        return Ok(None);\n    }\n    Price::from_decimal_dp(value, precision)\n        .map(Some)\n        .map_err(|e| anyhow::anyhow!(\"invalid price `{value}` at precision {precision}: {e}\"))\n}\n\nfn lighter_fee_to_commission(\n    fee_ticks: Option<i32>,\n    currency: Currency,\n) -> Result<Money, LighterCommissionError> {\n    let ticks = fee_ticks.unwrap_or(0);\n    let amount = Decimal::new(i64::from(ticks), FEE_DECIMALS);\n    Money::from_decimal(amount, currency).map_err(|e| LighterCommissionError::new(e.to_string()))\n}\n\nfn nautilus_order_side(side: LighterOrderSide) -> OrderSide {\n    match side {\n        LighterOrderSide::Buy => OrderSide::Buy,\n        LighterOrderSide::Sell => OrderSide::Sell,\n    }\n}\n","sourceCodeStart":1184,"sourceCodeEnd":1220,"githubUrl":"https://github.com/nautechsystems/nautilus_trader/blob/18893faf8b356be3320add8de2f861b0b647cf06/crates/adapters/lighter/src/websocket/parse.rs#L1184-L1220","documentation":"parse_optional_price converts a Lighter decimal price into a Nautilus Price at a fixed precision using Price::from_decimal_dp. Zero prices are treated as 'no price' and return Ok(None); any non-zero value that cannot be represented exactly at the given precision (excess decimal places, out-of-range magnitude) produces this error wrapping the underlying failure.","triggerScenarios":"parse_ws_order_status_report or lighter_order_shape receives a non-zero Lighter price whose decimal representation does not fit the instrument's price precision (e.g. 0.123456 with precision 2), or a value beyond Price's representable range.","commonSituations":"Exchange changes tick size and emits prices finer than the locally configured precision; instrument registered with wrong precision; a synthetic/derived price (e.g. stop trigger computed elsewhere) carries more dp than allowed; test fixtures using arbitrary precision decimals.","solutions":["Round/quantize the Decimal to the target precision before calling: value.round_dp(precision), accepting the small quantization, or reject upstream if the difference is material.","Verify the instrument's price precision used to compute the `precision` argument matches the exchange's current tick size; refresh the instrument if stale.","Log the raw value and precision on failure to see whether the value or the precision is wrong.","If Lighter genuinely emits finer prices after a market change, update the instrument definition in your catalog rather than hacking the parser."],"exampleFix":"// before\nPrice::from_decimal_dp(value, precision)\n    .map(Some)\n    .map_err(|e| anyhow::anyhow!(\"invalid price `{value}` at precision {precision}: {e}\"))\n\n// after\nlet value = value.round_dp(u32::from(precision));\nPrice::from_decimal_dp(value, precision)\n    .map(Some)\n    .map_err(|e| anyhow::anyhow!(\"invalid price `{value}` at precision {precision}: {e}\"))","handlingStrategy":"validation","validationCode":"fn fits_precision(value: Decimal, precision: u8) -> bool {\n    value.scale() <= u32::from(precision) && value.is_finite()\n}","typeGuard":null,"tryCatchPattern":"match parse_optional_price(raw, precision) {\n    Ok(Some(p)) => p,\n    Ok(None) => return Ok(None),\n    Err(e) => { log::warn!(\"price {raw} unusable at precision {precision}: {e}\"); return Ok(None); }\n}","preventionTips":["Quantize exchange decimals to the instrument's precision before constructing Price.","Refresh instrument definitions when the exchange changes tick size.","Treat a failed price parse as a skip-with-warning for non-critical reports rather than a stream failure."],"tags":["rust","parsing","price","precision"],"backgroundTag":"invalid-argument-format","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"}