{"record":{"id":"cf2581c8c613b56e","repo":"nautechsystems/nautilus_trader","slug":"non-positive-candle-close","errorCode":null,"errorMessage":"non-positive candle close `{}`","messagePattern":"non-positive candle close `(.+?)`","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"crates/adapters/lighter/src/http/parse.rs","lineNumber":202,"sourceCode":"    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\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)","sourceCodeStart":184,"sourceCodeEnd":220,"githubUrl":"https://github.com/nautechsystems/nautilus_trader/blob/18893faf8b356be3320add8de2f861b0b647cf06/crates/adapters/lighter/src/http/parse.rs#L184-L220","documentation":"parse_candle_bar requires a candle's close price to be strictly positive. A non-positive close means the candle record from Lighter is invalid (placeholder, corrupt, or untraded market data) and cannot become a Bar. The message includes the offending value.","triggerScenarios":"parse_candle_bar receiving a LighterCandle with close <= 0 while converting candles via parse_bars.","commonSituations":"Empty/illiquid markets returning zeroed candles; upstream outages producing placeholder data; bad fixture data in tests.","solutions":["Filter candles with close <= 0 out before parsing","Verify the Lighter API response contains real trade data for the interval","Check market status (newly listed/delisted markets may return zeros)","Correct fixture or mock data to positive values"],"exampleFix":"// before\nlet bar = parse_candle_bar(&candle, ...)?;\n// after\nif candle.close <= Decimal::ZERO { continue; }\nlet bar = parse_candle_bar(&candle, ...)?;","handlingStrategy":"validation","validationCode":"if candle.close <= Decimal::ZERO {\n    return Err(anyhow::anyhow!(\"skip candle: non-positive close {}\", candle.close));\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 close\") => continue,\n    Err(e) => return Err(e),\n};","preventionTips":["Pre-check all four OHLC values are positive before calling the parser","Sanity-check upstream API responses during exchange incidents","Use real (non-zeroed) sample data in tests","Filter placeholder candles for newly listed or halted markets"],"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"}