{"record":{"id":"b6f09bfff1d8b986","repo":"nautechsystems/nautilus_trader","slug":"non-positive-candle-open","errorCode":null,"errorMessage":"non-positive candle open `{}`","messagePattern":"non-positive candle open `(.+?)`","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"crates/adapters/lighter/src/http/parse.rs","lineNumber":187,"sourceCode":"        trade_id,\n        ts_event,\n        ts_init,\n    )\n    .context(\"failed to construct TradeTick from Lighter trade\")\n}\n\n/// Parses a Lighter candle into a Nautilus [`Bar`].\n///\n/// # Errors\n///\n/// Returns an error if any price, volume, or timestamp field cannot be converted.\npub fn parse_candle_bar(\n    candle: &LighterCandle,\n    bar_type: BarType,\n    instrument: &InstrumentAny,\n    ts_init: UnixNanos,\n) -> anyhow::Result<Bar> {\n    anyhow::ensure!(\n        candle.open > Decimal::ZERO,\n        \"non-positive candle open `{}`\",\n        candle.open\n    );\n    anyhow::ensure!(\n        candle.high > Decimal::ZERO,\n        \"non-positive candle high `{}`\",\n        candle.high\n    );\n    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","sourceCodeStart":169,"sourceCodeEnd":205,"githubUrl":"https://github.com/nautechsystems/nautilus_trader/blob/18893faf8b356be3320add8de2f861b0b647cf06/crates/adapters/lighter/src/http/parse.rs#L169-L205","documentation":"parse_candle_bar validates that a Lighter candle's open price is strictly positive before building a Bar. Lighter data must have OHLC values > 0 (Price cannot be zero or negative); a non-positive open means corrupt, placeholder, or malformed API data. The error includes the offending value.","triggerScenarios":"parse_candle_bar receiving a LighterCandle whose open field is <= 0 (zero or negative Decimal), typically via parse_bars processing a /candles HTTP response.","commonSituations":"Exchange API returning zeroed-out candles for illiquid/new markets or delisted pairs; fixtures or mocks with placeholder zeros; upstream data glitches during outages.","solutions":["Skip or filter candles with open <= 0 before calling parse_candle_bar/parse_bars","Check the upstream Lighter API response for corrupt or placeholder candle records","Confirm the instrument/market is active and has traded (delisted or never-traded markets may yield zeros)","Validate fixture/test data contains positive OHLC values"],"exampleFix":"// before\nlet bars: Vec<Bar> = candles.iter().map(|c| parse_candle_bar(c, bar_type, &inst, ts_init)).collect::<Result<_>>()?;\n// after\nlet bars: Vec<Bar> = candles.iter().filter(|c| c.open > Decimal::ZERO).map(|c| parse_candle_bar(c, bar_type, &inst, ts_init)).collect::<Result<_>>()?;","handlingStrategy":"validation","validationCode":"if candle.open <= Decimal::ZERO {\n    return Err(anyhow::anyhow!(\"skip candle: non-positive open {}\", candle.open));\n}","typeGuard":"fn has_positive_ohlc(c: &LighterCandle) -> bool {\n    c.open > Decimal::ZERO && c.high > Decimal::ZERO && c.low > Decimal::ZERO && c.close > Decimal::ZERO\n}","tryCatchPattern":"let bar = match parse_candle_bar(&candle, bar_type, instrument, ts_init) {\n    Ok(b) => b,\n    Err(e) if e.to_string().contains(\"non-positive candle open\") => continue,\n    Err(e) => return Err(e),\n};","preventionTips":["Pre-filter candles for positive OHLC before parsing","Validate market activity for the requested interval (empty markets yield zeros)","Keep fixtures free of placeholder zero values","Log and skip invalid candles instead of failing whole batch parses where acceptable"],"tags":["rust","data-validation","candles","adapter"],"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"}