nautechsystems/nautilus_trader · error · anyhow::Error

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

Error message

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

What it means

During USD-M futures instrument parsing (parse_usdm_instrument_with_fees), each symbol's contractType string is mapped to an instrument kind. Only PERPETUAL, TRADIFI_PERPETUAL, CURRENT_MONTH, NEXT_MONTH, CURRENT_QUARTER and NEXT_QUARTER are recognized; any other contractType bails with this error, naming the symbol and the unrecognized type.

Source

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

    maker_fee: Option<Decimal>,
    taker_fee: Option<Decimal>,
    ts_event: UnixNanos,
    ts_init: UnixNanos,
) -> anyhow::Result<InstrumentAny> {
    enum ContractKind {
        CryptoPerpetual,
        TradFi(AssetClass),
        Delivery,
    }

    let contract_kind = match symbol.contract_type.as_str() {
        CONTRACT_TYPE_PERPETUAL => ContractKind::CryptoPerpetual,
        CONTRACT_TYPE_TRADIFI_PERPETUAL => ContractKind::TradFi(parse_tradifi_asset_class(symbol)?),
        CONTRACT_TYPE_CURRENT_MONTH
        | CONTRACT_TYPE_NEXT_MONTH
        | CONTRACT_TYPE_CURRENT_QUARTER
        | CONTRACT_TYPE_NEXT_QUARTER => ContractKind::Delivery,
        _ => anyhow::bail!(
            "Unsupported USD-M contract type '{}' for symbol '{}'",
            symbol.contract_type,
            symbol.symbol,
        ),
    };

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

    let quote_currency = get_currency(symbol.quote_asset.as_str());
    let settlement_currency = get_currency(symbol.margin_asset.as_str());

    let instrument_id = format_instrument_id(&symbol.symbol, BinanceProductType::UsdM);

View on GitHub (pinned to a4b06ed870)

Solutions

  1. Look up the reported symbol in the live USD-M exchangeInfo and note its contractType value.
  2. Update NautilusTrader to a release supporting the new contract type, or open an issue with the symbol and the raw type string.
  3. Filter that symbol out of instrument loading until the adapter supports it.
  4. In tests, use one of the six recognized contractType strings.

Example fix

// before (fixture)
// "contractType": "SOME_NEW_TYPE"      -> Unsupported USD-M contract type
// after
// "contractType": "CURRENT_QUARTER"   // one of the six supported values
Defensive patterns

Strategy: try-catch

Validate before calling

const SUPPORTED_USDM: [&str; 6] = [
    "PERPETUAL", "TRADIFI_PERPETUAL", "CURRENT_MONTH",
    "NEXT_MONTH", "CURRENT_QUARTER", "NEXT_QUARTER",
];

fn usdm_contract_type_supported(ct: &str) -> bool {
    SUPPORTED_USDM.contains(&ct)
}

Type guard

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

Try / catch

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

Prevention

When it happens

Trigger: Loading the USD-M exchangeInfo when it contains a symbol whose contractType falls outside the six supported constants — for example a newly introduced delivery cycle or contract family that the adapter version predates.

Common situations: Binance launches a new contract type (as when TRADIFI_PERPETUAL was added); an older NautilusTrader build runs against a live venue that has since extended contractType; test fixtures hand-write an unknown contractType.

Related errors


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