nautechsystems/nautilus_trader · error

Trade bin missing open price for {instrument_id}

Error message

Trade bin missing open price for {instrument_id}

What it means

parse_trade_bin converts a BitMEX tradeBin into a Nautilus Bar and requires the OHLC fields to be present. If the bin's open price is null (BitMEX may omit fields on partial/empty bins), the parser fails with this message naming the instrument.

Source

Thrown at crates/adapters/bitmex/src/http/parse.rs:739

}

/// Converts a BitMEX trade-bin record into a Nautilus [`Bar`].
///
/// # Errors
///
/// Returns an error when required OHLC fields are missing from the payload.
pub fn parse_trade_bin(
    bin: &BitmexTradeBin,
    instrument: &InstrumentAny,
    bar_type: &BarType,
    ts_init: UnixNanos,
) -> anyhow::Result<Bar> {
    let instrument_id = bar_type.instrument_id();
    let price_precision = instrument.price_precision();

    let open = bin
        .open
        .ok_or_else(|| anyhow::anyhow!("Trade bin missing open price for {instrument_id}"))?;
    let high = bin
        .high
        .ok_or_else(|| anyhow::anyhow!("Trade bin missing high price for {instrument_id}"))?;
    let low = bin
        .low
        .ok_or_else(|| anyhow::anyhow!("Trade bin missing low price for {instrument_id}"))?;
    let close = bin
        .close
        .ok_or_else(|| anyhow::anyhow!("Trade bin missing close price for {instrument_id}"))?;

    let open = Price::new(open, price_precision);
    let high = Price::new(high, price_precision);
    let low = Price::new(low, price_precision);
    let close = Price::new(close, price_precision);

    let (open, high, low, close) =
        normalize_trade_bin_prices(open, high, low, close, &bin.symbol, Some(bar_type));

View on GitHub (pinned to 18893faf8b)

Solutions

  1. Set partial=false (or exclude the last bin) so only closed, complete bins are requested.
  2. Trim the end timestamp back before the current bucket boundary.
  3. Check adjacent fields (high/low/close) — if all are null, the bin is empty and should be skipped.
  4. Retry the request later if the gap is transient; verify the bin exists on the BitMEX /trade/bins endpoint.

Example fix

// before
let bars = client.request_bars(bar_type, start, end, limit, true).await?;
// after
let bars = client.request_bars(bar_type, start, end, limit, false).await?;
Defensive patterns

Strategy: fallback

Validate before calling

let open = bin.open
    .or_else(|| log_warn_then_none(&bin, instrument_id))
    .ok_or_else(|| anyhow::anyhow!("Trade bin missing open price for {instrument_id}"))?;

Try / catch

match client.request_bars(bar_type, start, end, limit, partial).await {
    Ok(bars) => bars,
    Err(e) if e.to_string().contains("missing open price") => {
        log::warn!("partial bin received; retrying without last bar: {e}");
        client.request_bars(bar_type, start, end_trimmed, limit, false).await?
    }
    Err(e) => return Err(e),
}

Prevention

When it happens

Trigger: request_bars receiving a tradeBin record with a null open field — typically the still-forming (partial) latest bin when partial=true, or venue-side gaps in bin data.

Common situations: Requesting bars that include the current, not-yet-closed bucket; venue maintenance windows producing incomplete bins; low-liquidity symbols where the bin has no trades.

Understand the failure class

Background: "must not be empty", "cannot be empty" — required-field validation errors across open-source libraries — this error's family across 41 libraries.

Related errors


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