nautechsystems/nautilus_trader · error · anyhow::Error

unsupported inverse contract variant: {other:?}

Error message

unsupported inverse contract variant: {other:?}

What it means

parse_inverse_instrument matches BybitContractType to map InversePerpetual to CryptoPerpetual and InverseFutures to CryptoFuture. Any other variant falls into a catch-all arm returning this error, meaning the adapter encountered an inverse contract type it cannot translate into a Nautilus instrument.

Source

Thrown at crates/adapters/bybit/src/common/parse.rs:708

                .size_increment(size_increment)
                .maybe_lot_size(lot_size)
                .maybe_max_quantity(max_quantity)
                .maybe_min_quantity(min_quantity)
                .maybe_min_notional(min_notional)
                .maybe_max_price(max_price)
                .maybe_min_price(min_price)
                .margin_init(default_margin())
                .margin_maint(default_margin())
                .maker_fee(maker_fee)
                .taker_fee(taker_fee)
                .maybe_info(info)
                .ts_event(ts_event)
                .ts_init(ts_init)
                .build()
                .unwrap();
            Ok(InstrumentAny::CryptoFuture(instrument))
        }
        other => Err(anyhow::anyhow!(
            "unsupported inverse contract variant: {other:?}"
        )),
    }
}

fn build_instrument_info(
    symbol_type: Option<BybitSymbolType>,
    xstock_multiplier: Option<&str>,
) -> Option<Params> {
    let symbol_type = symbol_type?;
    let value = symbol_type.as_str()?;
    let mut info = Params::new();
    info.insert(
        "symbol_type".to_string(),
        serde_json::Value::String(value.to_string()),
    );

    if symbol_type == BybitSymbolType::Xstocks

View on GitHub (pinned to 18893faf8b)

Solutions

  1. Upgrade the adapter to a version that handles the new BybitContractType variant
  2. Skip symbols with unsupported contract types and log them instead of failing the request
  3. Add an explicit mapping or early-return arm for the new variant in parse_inverse_instrument
  4. Narrow the instrument request (symbols filter) to exclude the unsupported contract

Example fix

// before
other => Err(anyhow::anyhow!("unsupported inverse contract variant: {other:?}")),
// after
other => {
    tracing::debug!(?other, "skipping unsupported inverse contract variant");
    Ok(None)
}
Defensive patterns

Strategy: type-guard

Validate before calling

fn is_supported_inverse(ct: &BybitContractType) -> bool {
    matches!(ct, BybitContractType::InversePerpetual | BybitContractType::InverseFutures)
}

Type guard

fn as_supported_inverse(ct: &BybitContractType) -> Option<&BybitContractType> {
    matches!(ct, BybitContractType::InversePerpetual | BybitContractType::InverseFutures).then_some(ct)
}

Try / catch

match parse_inverse_instrument(&def, &fee, ts_event, ts_init) {
    Ok(inst) => instruments.push(inst),
    Err(e) if e.to_string().contains("unsupported inverse contract variant") => {
        tracing::debug!(symbol = %def.symbol, "skipping unsupported inverse contract");
    }
    Err(e) => return Err(e),
}

Prevention

When it happens

Trigger: An instruments-info response for category=inverse yields a contractType variant outside {InversePerpetual, InverseFutures} (e.g. a newly listed product type), and the symbol is passed through parse_inverse_instrument via request_instruments or request_instruments_with_statuses.

Common situations: Bybit extending its v5 API with new inverse contract types; stale adapter versions behind the exchange API; broad category queries returning instruments the caller did not expect.

Related errors


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