{"record":{"id":"e0751ef359f62e05","repo":"nautechsystems/nautilus_trader","slug":"invalid-quantity-value-at-precision-precision","errorCode":null,"errorMessage":"invalid quantity `{value}` at precision {precision}: {e}","messagePattern":"invalid quantity `(.+?)` at precision (.+?): (.+?)","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"crates/adapters/lighter/src/common/parse.rs","lineNumber":121,"sourceCode":"///\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\n/// is out of range.\npub fn parse_quantity(value: &str, precision: u8) -> anyhow::Result<Quantity> {\n    anyhow::ensure!(\n        precision <= MAX_DECIMALS,\n        \"size precision {precision} exceeds maximum {MAX_DECIMALS}\",\n    );\n    let decimal =\n        Decimal::from_str(value).map_err(|e| anyhow::anyhow!(\"invalid quantity `{value}`: {e}\"))?;\n    anyhow::ensure!(decimal.is_sign_positive(), \"negative quantity `{value}`\");\n    Quantity::from_decimal_dp(decimal, precision)\n        .map_err(|e| anyhow::anyhow!(\"invalid quantity `{value}` at precision {precision}: {e}\"))\n}\n\n/// Converts a [`Decimal`] into a Nautilus [`Price`] at the requested precision.\n///\n/// Use this when the wire value has already been deserialized as a [`Decimal`]\n/// (the standard pattern for model fields tagged with `deserialize_decimal`).\n///\n/// # Errors\n///\n/// Returns an error if `precision` exceeds [`MAX_DECIMALS`] or if the value\n/// is out of [`Price`] range.\npub fn price_from_decimal(value: Decimal, precision: u8) -> anyhow::Result<Price> {\n    anyhow::ensure!(\n        precision <= MAX_DECIMALS,\n        \"price precision {precision} exceeds maximum {MAX_DECIMALS}\",\n    );\n    Price::from_decimal_dp(value, precision)\n        .map_err(|e| anyhow::anyhow!(\"invalid price `{value}` at precision {precision}: {e}\"))","sourceCodeStart":103,"sourceCodeEnd":139,"githubUrl":"https://github.com/nautechsystems/nautilus_trader/blob/18893faf8b356be3320add8de2f861b0b647cf06/crates/adapters/lighter/src/common/parse.rs#L103-L139","documentation":"After the string parses as a Decimal and passes the non-negative check, parse_quantity calls Quantity::from_decimal_dp. This error means the value is out of Quantity's representable fixed-precision range at the requested precision (or the precision conversion failed) — e.g. a magnitude far beyond ~10^18, or a value that cannot be represented at the given precision. Value and precision are included in the message.","triggerScenarios":"Calling parse_quantity with a valid, non-negative decimal string whose magnitude overflows the Quantity fixed-point range, or whose representation conflicts with the requested precision.","commonSituations":"Malicious or corrupt feed payloads with absurd sizes; a market whose size_decimals is misreported so values scale wrongly; unit tests probing Quantity bounds; accidentally passing a raw mantissa (unscaled tick count) as a decimal string.","solutions":["Verify size_decimals for the market matches orderBookDetails — a wrong precision mis-scales the value.","Range-check the magnitude against plausible instrument maximums before parsing and reject out-of-band values upstream.","Inspect the raw payload: overflow-sized quantities indicate a corrupted or fabricated message; drop and log.","Ensure you are not passing an unscaled mantissa string (e.g. \"500000000000\") where a human-readable decimal was expected — use parse_quantity_from_ticks for mantissas."],"exampleFix":"// before\nlet qty = parse_quantity(&ticks.to_string(), precision)?; // raw mantissa as string\n// after\nlet qty = parse_quantity_from_ticks(ticks, precision)?;","handlingStrategy":"validation","validationCode":"fn quantity_plausible(value: &str, max_qty: f64) -> bool {\n    value.parse::<f64>().map(|v| v.is_finite() && v >= 0.0 && v <= max_qty).unwrap_or(false)\n}","typeGuard":null,"tryCatchPattern":"match parse_quantity(raw, precision) {\n    Ok(q) => q,\n    Err(e) if e.to_string().contains(\"at precision\") => {\n        tracing::error!(raw = %raw, \"quantity out of Quantity range; dropping update\");\n        return Ok(());\n    }\n    Err(e) => return Err(e.into()),\n}","preventionTips":["Range-check magnitudes against instrument max quantity before conversion","Use parse_quantity_from_ticks for raw mantissas — never stringify a mantissa into parse_quantity","Verify size_decimals against orderBookDetails to avoid mis-scaled values","Drop and log overflow-sized payloads as data-integrity events"],"tags":["rust","parsing","overflow","quantity"],"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"}