nautechsystems/nautilus_trader · error

unsupported Derive instrument type for trades: {other:?}

Error message

unsupported Derive instrument type for trades: {other:?}

What it means

The Derive adapter can only map Nautilus instruments of type CryptoPerpetual, CryptoOption, or CurrencyPair to a DeriveInstrumentType when creating/dispatching trades. Any other instrument kind (e.g. FuturesContract, Equity, etc.) hits the catch-all arm and bails. It is an adapter capability guard, not a data corruption issue.

Source

Thrown at crates/adapters/derive/src/data.rs:2392

    DeriveTickerInterval::from_str(&interval)
        .with_context(|| format!("invalid Derive ticker interval `{interval}`"))?;
    Ok(interval)
}

fn trade_channel(instrument: &InstrumentAny) -> anyhow::Result<String> {
    let instrument_type = derive_instrument_type(instrument)?.to_string();
    let instrument_id = instrument.id();
    let currency = currency_from_instrument_id(&instrument_id)?;
    Ok(trades_channel(&instrument_type, currency))
}

fn derive_instrument_type(instrument: &InstrumentAny) -> anyhow::Result<DeriveInstrumentType> {
    match instrument {
        InstrumentAny::CryptoPerpetual(_) => Ok(DeriveInstrumentType::Perp),
        InstrumentAny::CryptoOption(_) => Ok(DeriveInstrumentType::Option),
        InstrumentAny::CurrencyPair(_) => Ok(DeriveInstrumentType::Erc20),
        other => anyhow::bail!("unsupported Derive instrument type for trades: {other:?}"),
    }
}

fn currency_from_instrument_id(instrument_id: &InstrumentId) -> anyhow::Result<&str> {
    anyhow::ensure!(
        instrument_id.venue == *DERIVE_VENUE,
        "instrument ID `{instrument_id}` is not for venue {}",
        DERIVE_VENUE.as_str(),
    );

    instrument_id
        .symbol
        .as_str()
        .split_once('-')
        .and_then(|(currency, _)| (!currency.is_empty()).then_some(currency))
        .ok_or_else(|| anyhow::anyhow!("cannot derive currency from {instrument_id}"))
}

View on GitHub (pinned to 18893faf8b)

Solutions

  1. Use a supported instrument type (CryptoPerpetual, CryptoOption, or CurrencyPair) when loading/subscribing Derive instruments
  2. Check that instrument providers load Derive instruments as CurrencyPair for spot markets, not as another type
  3. If a legitimate instrument type is missing, add an arm to derive_instrument_type in crates/adapters/derive/src/data.rs mapping it to the correct DeriveInstrumentType
  4. Filter unsupported instrument kinds out before subscribing to trade data

Example fix

// before
let instrument = loader.load_instrument(id)?; // returns FuturesContract
// after
let instrument = loader.load_instrument_as_currency_pair(id)?; // CurrencyPair is supported
Defensive patterns

Strategy: type-guard

Validate before calling

fn is_derive_trade_capable(i: &InstrumentAny) -> bool {
    matches!(i, InstrumentAny::CryptoPerpetual(_) | InstrumentAny::CryptoOption(_) | InstrumentAny::CurrencyPair(_))
}
if !is_derive_trade_capable(&inst) { skip_subscription(inst.id()); }

Type guard

fn as_supported(i: &InstrumentAny) -> Option<&DeriveInstrumentType> {
    match i {
        InstrumentAny::CryptoPerpetual(_) => Some(&DeriveInstrumentType::Perp),
        InstrumentAny::CryptoOption(_) => Some(&DeriveInstrumentType::Option),
        InstrumentAny::CurrencyPair(_) => Some(&DeriveInstrumentType::Erc20),
        _ => None,
    }
}

Try / catch

match derive_instrument_type(&inst) {
    Ok(t) => proceed(t),
    Err(e) => { log::warn!("skipping {}: {e}", inst.id()); }
}

Prevention

When it happens

Trigger: Calling trade-parsing paths (e.g. parse_md_message dispatching trade prints, or create_architect_trade_id-style flows in test harnesses) with an InstrumentAny that is not CryptoPerpetual, CryptoOption, or CurrencyPair.

Common situations: Subscribing to trades on a Derive instrument loaded as the wrong instrument type; feeding instruments from another venue into the Derive adapter; a new instrument kind added upstream but not yet supported by derive_instrument_type.

Understand the failure class

Background: UnsupportedOperationException and "is not supported" errors: when a library deliberately refuses a call — this error's family across 30 libraries.

Related errors


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