nautechsystems/nautilus_trader · error

invalid candle high

Error message

invalid candle high: {e}

What it means

This wraps a failure converting the candle's high Decimal to a Price at the instrument's price_precision inside parse_candle_bar. Price::from_decimal_dp rejected the value, so the candle cannot be represented at the instrument's precision. The original conversion error is preserved as the cause.

Solutions

  1. Inspect the chained cause for the precise from_decimal_dp failure
  2. Confirm the instrument used has the correct price_precision for this market
  3. Validate the candle high is finite and sane before conversion
  4. Verify the raw API payload for anomalous high values

Example fix

// before
let high = Price::from_decimal_dp(candle.high, price_precision)?;
// after
let high = Price::from_decimal_dp(candle.high.round_dp(price_precision as u32), price_precision)?;
Defensive patterns

Strategy: try-catch

Validate before calling

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

Type guard

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

Try / catch

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

Prevention

When it happens

Trigger: LighterCandle.high failing Price::from_decimal_dp(high, price_precision) — typically a non-finite decimal or a value incompatible with the instrument's precision when parsing candles via parse_bars.

Common situations: Corrupt upstream highs (NaN/inf); instrument precision mismatched with the market's tick size; passing the wrong instrument to parse_candle_bar.

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/53ad3e95d8433b90. Report an issue: GitHub.

Appendix: source

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

        "non-positive candle low `{}`",
        candle.low
    );
    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`].
///

View on GitHub (pinned to 18893faf8b)