{"record":{"id":"0cbb238f038e0a1f","repo":"nautechsystems/nautilus_trader","slug":"invalid-candle-open-e","errorCode":null,"errorMessage":"invalid candle open: {e}","messagePattern":"invalid candle open: (.+?)","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"crates/adapters/lighter/src/http/parse.rs","lineNumber":215,"sourceCode":"    anyhow::ensure!(\n        candle.low > Decimal::ZERO,\n        \"non-positive candle low `{}`\",\n        candle.low\n    );\n    anyhow::ensure!(\n        candle.close > Decimal::ZERO,\n        \"non-positive candle close `{}`\",\n        candle.close\n    );\n\n    let timestamp_ms =\n        u64::try_from(candle.timestamp).context(\"negative Lighter candle timestamp\")?;\n    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","sourceCodeStart":197,"sourceCodeEnd":233,"githubUrl":"https://github.com/nautechsystems/nautilus_trader/blob/18893faf8b356be3320add8de2f861b0b647cf06/crates/adapters/lighter/src/http/parse.rs#L197-L233","documentation":"After passing the positivity checks, parse_candle_bar converts the candle's open Decimal into a Price rounded to the instrument's price precision via Price::from_decimal_dp. If that conversion fails (e.g. NaN, non-finite, or precision-related failure), the error is wrapped as 'invalid candle open'. The underlying cause from from_decimal_dp is chained in {e}.","triggerScenarios":"A LighterCandle.open Decimal that Price::from_decimal_dp rejects for the instrument's price_precision — e.g. non-finite decimal values from upstream data, or a mismatch between the instrument definition and the candle's decimal scale.","commonSituations":"Upstream API emitting NaN/inf-like values; using an instrument whose price_precision doesn't accommodate the candle's decimals; parsing candles with the wrong instrument object.","solutions":["Read the chained cause {e} to see why Price::from_decimal_dp failed","Ensure the correct instrument (matching the bar_type/instrument_id) with the right price_precision is passed in","Sanitize/validate candle decimals (finite, within instrument price bounds) before parsing","Check the Lighter API response for anomalous open values"],"exampleFix":"// before\nlet open = Price::from_decimal_dp(candle.open, price_precision)\n    .map_err(|e| anyhow::anyhow!(\"invalid candle open: {e}\"))?;\n// after\nanyhow::ensure!(candle.open.is_finite(), \"non-finite candle open\");\nlet open = Price::from_decimal_dp(candle.open, price_precision)\n    .map_err(|e| anyhow::anyhow!(\"invalid candle open: {e}\"))?;","handlingStrategy":"try-catch","validationCode":"anyhow::ensure!(candle.open.is_finite(), \"non-finite candle open: {}\", candle.open);","typeGuard":"fn convertible_open(c: &LighterCandle, precision: u8) -> bool {\n    c.open.is_finite() && c.open > Decimal::ZERO\n}","tryCatchPattern":"let open = Price::from_decimal_dp(candle.open, price_precision)\n    .map_err(|e| anyhow::anyhow!(\"invalid candle open: {e}\"))\n    .with_context(|| format!(\"candle for {}\", instrument.id()))?;","preventionTips":["Ensure the instrument passed to the parser is the one matching the candle's instrument_id","Confirm the instrument's price_precision reflects the market tick size","Validate candle decimals are finite before conversion","Check adapter/API version alignment when decimal scaling changes"],"tags":["rust","price-conversion","candles","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-14T00:17:10.932Z"}