nautechsystems/nautilus_trader · error · anyhow::Error

Unsupported COIN-M contract type '{}' for symbol '{}'

Error message

Unsupported COIN-M contract type '{}' for symbol '{}'

What it means

parse_coinm_instrument_with_fees accepts only three COIN-M contract types: PERPETUAL, CURRENT_QUARTER and NEXT_QUARTER (coin-margined contracts have no monthly delivery cycle). Any other contract_type string bails with the symbol and the unsupported value.

Source

Thrown at crates/adapters/binance/src/common/parse.rs:465

) -> anyhow::Result<InstrumentAny> {
    parse_coinm_instrument_with_fees(symbol, None, None, ts_event, ts_init)
}

pub(crate) fn parse_coinm_instrument_with_fees(
    symbol: &BinanceFuturesCoinSymbol,
    maker_fee: Option<Decimal>,
    taker_fee: Option<Decimal>,
    ts_event: UnixNanos,
    ts_init: UnixNanos,
) -> anyhow::Result<InstrumentAny> {
    let is_perpetual = symbol.contract_type == CONTRACT_TYPE_PERPETUAL;
    let is_delivery = matches!(
        symbol.contract_type.as_str(),
        CONTRACT_TYPE_CURRENT_QUARTER | CONTRACT_TYPE_NEXT_QUARTER
    );

    if !is_perpetual && !is_delivery {
        anyhow::bail!(
            "Unsupported COIN-M contract type '{}' for symbol '{}'",
            symbol.contract_type,
            symbol.symbol,
        );
    }

    if symbol.contract_status != Some(BinanceContractStatus::Trading) {
        anyhow::bail!(
            "Symbol '{}' is not trading (status: {:?})",
            symbol.symbol,
            symbol.contract_status
        );
    }

    let base_currency = get_currency(symbol.base_asset.as_str());
    let quote_currency = get_currency(symbol.quote_asset.as_str());

    // COIN-M contracts are settled in the base currency (inverse)

View on GitHub (pinned to a4b06ed870)

Solutions

  1. Check the reported symbol's contractType in the live COIN-M exchangeInfo.
  2. Update NautilusTrader to a release that recognizes the new type, or open an issue including the symbol and raw string.
  3. Exclude the symbol from COIN-M instrument loading until supported.
  4. In tests, use only PERPETUAL / CURRENT_QUARTER / NEXT_QUARTER for COIN-M fixtures.

Example fix

// before (COIN-M fixture copied from USD-M)
// "contract_type": "CURRENT_MONTH"     -> Unsupported COIN-M contract type
// after
// "contract_type": "CURRENT_QUARTER"   // supported on COIN-M
Defensive patterns

Strategy: try-catch

Validate before calling

fn coinm_contract_type_supported(ct: &str) -> bool {
    matches!(ct, "PERPETUAL" | "CURRENT_QUARTER" | "NEXT_QUARTER")
}

Type guard

fn is_supported_coinm_contract_type(ct: &str) -> bool {
    matches!(ct, "PERPETUAL" | "CURRENT_QUARTER" | "NEXT_QUARTER")
}

Try / catch

match parse_coinm_instrument(&symbol, ts_event, ts_init) {
    Ok(inst) => instruments.push(inst),
    Err(e) if e.to_string().contains("Unsupported COIN-M contract type") => {
        tracing::warn!(symbol = %symbol.symbol, "skipping: {e}")
    }
    Err(e) => return Err(e),
}

Prevention

When it happens

Trigger: Loading the COIN-M exchangeInfo when a symbol's contractType is outside {PERPETUAL, CURRENT_QUARTER, NEXT_QUARTER} — for example a new contract family the adapter version predates.

Common situations: Binance introduces a new COIN-M contract type; running an older adapter against the live venue; fixtures with hand-written contractType values copied from USD-M payloads (which include monthly types COIN-M does not support).

Related errors


AI-assisted analysis of nautechsystems/nautilus_trader@a4b06ed870 (2026-08-16). Data as JSON: /api/errors/0b99a4343a08be27. Report an issue: GitHub.