nautechsystems/nautilus_trader · error

Funding rates not available for {product_type:?} instruments

Error message

Funding rates not available for {product_type:?} instruments

What it means

Funding rates only exist for derivative instruments on Bybit. When subscribing to funding rates, the adapter resolves the product type for the requested instrument and bails immediately if it resolves to Spot or Option, since those products have no funding payments.

Source

Thrown at crates/adapters/bybit/src/data.rs:1128

        self.spawn_ws(
            async move {
                ws.subscribe_trades(instrument_id)
                    .await
                    .context("trades subscription")
            },
            "trade subscription",
        );
        Ok(())
    }

    fn subscribe_funding_rates(&mut self, cmd: SubscribeFundingRates) -> anyhow::Result<()> {
        let instrument_id = cmd.instrument_id;
        let product_type = self
            .get_product_type_for_instrument(instrument_id)
            .unwrap_or(BybitProductType::Linear);

        if product_type == BybitProductType::Spot || product_type == BybitProductType::Option {
            anyhow::bail!("Funding rates not available for {product_type:?} instruments");
        }

        let guard = self.instruments.load();
        if let Some(instrument) = guard.get(&instrument_id)
            && !matches!(instrument, InstrumentAny::CryptoPerpetual(_))
        {
            anyhow::bail!("Funding rates only available for perpetuals, not {instrument_id}");
        }

        let mut should_subscribe = false;
        self.ticker_subs.rcu(|m| {
            let entry = m.entry(instrument_id).or_default();
            should_subscribe = entry.is_empty();
            entry.insert("funding");
        });

        if should_subscribe {
            let ws = self

View on GitHub (pinned to 18893faf8b)

Solutions

  1. Subscribe using the perpetual instrument ID (e.g. BTCUSDT-PERP.Linear) not spot
  2. Ensure the instrument-to-product-type map registers the correct product type so resolution doesn't default wrongly
  3. Filter out Spot and Option instruments before bulk funding-rate subscriptions

Example fix

// before
subscribe_funding_rates(BTCUSDT.SPOT) // bails
// after
subscribe_funding_rates(BTCUSDT-PERP.LINEAR) // perpetual
Defensive patterns

Strategy: validation

Validate before calling

let pt = client.get_product_type_for_instrument(instrument_id).unwrap_or(BybitProductType::Linear);
if matches!(pt, BybitProductType::Spot | BybitProductType::Option) {
    skip_funding_subscription(instrument_id);
}

Type guard

fn supports_funding(inst: &InstrumentAny) -> bool {
    matches!(inst, InstrumentAny::CryptoPerpetual(_))
}

Try / catch

match client.subscribe_funding_rates(cmd) {
    Err(e) if e.to_string().contains("Funding rates") => {
        log::debug!("skipping funding for non-derivative: {e}");
    }
    r => r?,
}

Prevention

When it happens

Trigger: subscribe_funding_rates called with a Spot or Option instrument ID (or one whose product type defaults/resolves to Spot/Option), e.g. BTCUSDT on spot instead of the perpetual.

Common situations: Using an unqualified symbol that resolves to the spot instrument; configuring a funding-rate subscription across all instruments including options; copying a subscription loop from a derivatives-only venue.

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/b86401b4d7055933. Report an issue: GitHub.