{"record":{"id":"214bada5c18c90bb","repo":"nautechsystems/nautilus_trader","slug":"invalid-candle-volume-e","errorCode":null,"errorMessage":"invalid candle volume: {e}","messagePattern":"invalid candle volume: (.+?)","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"crates/adapters/lighter/src/http/parse.rs","lineNumber":228,"sourceCode":"    let ts_event = parse_millis_to_nanos(timestamp_ms)?;\n    let price_precision = instrument.price_precision();\n    let size_precision = instrument.size_precision();\n\n    let open = Price::from_decimal_dp(candle.open, price_precision)\n        .map_err(|e| anyhow::anyhow!(\"invalid candle open: {e}\"))?;\n    let high = Price::from_decimal_dp(candle.high, price_precision)\n        .map_err(|e| anyhow::anyhow!(\"invalid candle high: {e}\"))?;\n    let low = Price::from_decimal_dp(candle.low, price_precision)\n        .map_err(|e| anyhow::anyhow!(\"invalid candle low: {e}\"))?;\n    let close = Price::from_decimal_dp(candle.close, price_precision)\n        .map_err(|e| anyhow::anyhow!(\"invalid candle close: {e}\"))?;\n    anyhow::ensure!(\n        candle.volume_base.is_sign_positive(),\n        \"negative candle volume `{}`\",\n        candle.volume_base,\n    );\n    let volume = Quantity::from_decimal_dp(candle.volume_base, size_precision)\n        .map_err(|e| anyhow::anyhow!(\"invalid candle volume: {e}\"))?;\n\n    Bar::new_checked(bar_type, open, high, low, close, volume, ts_event, ts_init)\n        .context(\"failed to construct Bar from Lighter candle\")\n}\n\n/// Parses a Lighter historical funding row into a Nautilus [`FundingRateUpdate`].\n///\n/// Lighter returns `rate` as a magnitude and `direction` as the side paying\n/// the funding. Nautilus uses the conventional signed rate: positive when\n/// longs pay shorts and negative when shorts pay longs.\n///\n/// # Errors\n///\n/// Returns an error if the timestamp cannot be converted.\npub fn parse_funding_rate_update(\n    funding: &LighterFunding,\n    instrument_id: InstrumentId,\n    interval: Option<u16>,","sourceCodeStart":210,"sourceCodeEnd":246,"githubUrl":"https://github.com/nautechsystems/nautilus_trader/blob/18893faf8b356be3320add8de2f861b0b647cf06/crates/adapters/lighter/src/http/parse.rs#L210-L246","documentation":"parse_candle_bar converts a Lighter historical candle into a Nautilus Bar. The raw candle's volume must be sign-positive and quantizable to the bar type's size precision; if Quantity::from_decimal_dp fails (or volume is negative, caught by the preceding ensure), this error wraps the underlying precision/conversion failure. It prevents constructing a Bar with an unrepresentable volume.","triggerScenarios":"Parsing a /candles response whose candle has negative volume_base, or whose volume requires more decimal places than the bar type's size_precision supports (e.g. volume 1.00000005 with size_precision=4), causing from_decimal_dp rounding/precision rejection.","commonSituations":"Bar type built with too-coarse size_precision for the venue's quote volumes; malformed or adversarial candle data from the HTTP API; copying volumes from a different market with higher precision.","solutions":["Set the bar type's size_precision to at least the decimal places the venue reports for volume (Lighter's supported_volume_decimals).","Pre-normalize candle volume with Decimal rounding to size_precision before parsing.","Check the candle payload for negative or malformed volume values before parsing.","Inspect the inner message from Quantity::from_decimal_dp in the wrapped {e} to see the exact precision failure."],"exampleFix":"// before\nlet bar_type = BarType::new(instrument_id, aggregator, PriceType::Last); // size_precision=2\n// after\nlet bar_type = BarType::new(\n    instrument_id,\n    aggregator,\n    PriceType::Last,\n);\n// ensure aggregator's size_precision >= venue volume decimals (e.g. 6 for Lighter)","handlingStrategy":"validation","validationCode":"// Rust: validate candle before parse_candle_bar\nif !candle.volume_base.is_sign_positive() {\n    return Err(anyhow!(\"skip candle: negative volume {}\", candle.volume_base));\n}\nlet dp = candle.volume_base.fract().scale() as u32;\nanyhow::ensure!(dp <= size_precision as u32, \"volume dp {} > size_precision {}\", dp, size_precision);","typeGuard":null,"tryCatchPattern":"match parse_candle_bar(&bar_type, &candle, size_precision) {\n    Ok(bar) => bar,\n    Err(e) => { warn!(\"skipping candle: {e:#}\"); continue; }\n}","preventionTips":["Set bar type size_precision to match Lighter supported_size_decimals.","Reject candles with non-positive volume upstream.","Unit-test parsing against the fixture with edge-case volumes."],"tags":["rust","parsing","precision","candles"],"backgroundTag":"invalid-argument-value","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"}