nautechsystems/nautilus_trader · error

invalid candle low: {e}

Error message

invalid candle low: {e}

What it means

This error wraps a failure converting the candle's low Decimal into a Price with the instrument's price precision in parse_candle_bar. from_decimal_dp rejects values it cannot represent, so a malformed or precision-incompatible low produces this wrapped error.

Source

Thrown at crates/adapters/lighter/src/http/parse.rs:219

    );
    anyhow::ensure!(
        candle.close > Decimal::ZERO,
        "non-positive candle close `{}`",
        candle.close
    );

    let timestamp_ms =
        u64::try_from(candle.timestamp).context("negative Lighter candle timestamp")?;
    let ts_event = parse_millis_to_nanos(timestamp_ms)?;
    let price_precision = instrument.price_precision();
    let size_precision = instrument.size_precision();

    let open = Price::from_decimal_dp(candle.open, price_precision)
        .map_err(|e| anyhow::anyhow!("invalid candle open: {e}"))?;
    let high = Price::from_decimal_dp(candle.high, price_precision)
        .map_err(|e| anyhow::anyhow!("invalid candle high: {e}"))?;
    let low = Price::from_decimal_dp(candle.low, price_precision)
        .map_err(|e| anyhow::anyhow!("invalid candle low: {e}"))?;
    let close = Price::from_decimal_dp(candle.close, price_precision)
        .map_err(|e| anyhow::anyhow!("invalid candle close: {e}"))?;
    anyhow::ensure!(
        candle.volume_base.is_sign_positive(),
        "negative candle volume `{}`",
        candle.volume_base,
    );
    let volume = Quantity::from_decimal_dp(candle.volume_base, size_precision)
        .map_err(|e| anyhow::anyhow!("invalid candle volume: {e}"))?;

    Bar::new_checked(bar_type, open, high, low, close, volume, ts_event, ts_init)
        .context("failed to construct Bar from Lighter candle")
}

/// Parses a Lighter historical funding row into a Nautilus [`FundingRateUpdate`].
///
/// Lighter returns `rate` as a magnitude and `direction` as the side paying
/// the funding. Nautilus uses the conventional signed rate: positive when

View on GitHub (pinned to 18893faf8b)

Solutions

  1. Check the chained cause {e} for the exact conversion failure
  2. Use the instrument definition matching the candle's instrument_id and tick size
  3. Pre-validate that candle decimals are finite before parsing
  4. Inspect the raw response for malformed low values

Example fix

// before
let low = Price::from_decimal_dp(candle.low, price_precision)?;
// after
anyhow::ensure!(candle.low.is_finite(), "non-finite candle low");
let low = Price::from_decimal_dp(candle.low, price_precision)?;
Defensive patterns

Strategy: try-catch

Validate before calling

anyhow::ensure!(candle.low.is_finite(), "non-finite candle low: {}", candle.low);

Type guard

fn convertible_low(c: &LighterCandle, precision: u8) -> bool {
    c.low.is_finite() && c.low > Decimal::ZERO
}

Try / catch

let low = Price::from_decimal_dp(candle.low, price_precision)
    .map_err(|e| anyhow::anyhow!("invalid candle low: {e}"))
    .with_context(|| format!("candle for {}", instrument.id()))?;

Prevention

When it happens

Trigger: LighterCandle.low rejected by Price::from_decimal_dp(low, price_precision) during parse_candle_bar/parse_bars — e.g. non-finite decimals or precision conflicts with the instrument definition.

Common situations: Bad upstream lows (NaN/inf); wrong instrument (precision) supplied; API schema change altering decimal formatting of candle fields.

Understand the failure class

Background: "Invalid ... format", "must be in format X", "does not look like a ..." — invalid argument format errors across CLI tools and libraries — this error's family across 17 libraries.

Related errors


AI-assisted analysis of nautechsystems/nautilus_trader@18893faf8b (2026-09-08). Data as JSON: /api/errors/0334d921f64305f9. Report an issue: GitHub.