nautechsystems/nautilus_trader · error
Mark prices not available for Spot instruments
Error message
Mark prices not available for Spot instruments
What it means
This error is raised when subscribing to mark prices for a Spot instrument on Bybit. Bybit's WebSocket does not provide mark-price streams for Spot product types, so the adapter rejects the subscription early. The subscription is only valid for Linear, Inverse, and Option instruments.
Source
Thrown at crates/adapters/bybit/src/data.rs:1170
async move {
ws.subscribe_ticker(instrument_id)
.await
.context("ticker subscription for funding rates")
},
"funding rate subscription",
);
}
Ok(())
}
fn subscribe_mark_prices(&mut self, cmd: SubscribeMarkPrices) -> 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 {
anyhow::bail!("Mark prices not available for Spot instruments");
}
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("mark_prices");
});
if should_subscribe {
let ws = self
.get_ws_client_for_product(product_type)
.context("no WebSocket client for product type")?
.clone();
self.spawn_ws(
async move {
ws.subscribe_ticker(instrument_id)View on GitHub (pinned to 18893faf8b)
Solutions
- Use Linear (perpetual) or Inverse instrument IDs instead of Spot for mark-price subscriptions
- Skip mark-price subscription logic for Spot instruments in your strategy configuration
- Use last trade price / ticker data for Spot instruments instead of mark prices
Example fix
// before
let instrument_id = InstrumentId::from("BTCUSDT.SBYBIT"); // Spot
data_engine.subscribe_mark_prices(instrument_id);
// after
let instrument_id = InstrumentId::from("BTCUSDT-PERP.SBYBIT"); // Linear
data_engine.subscribe_mark_prices(instrument_id); Defensive patterns
Strategy: validation
Validate before calling
let instrument = cache.instrument(&instrument_id).expect("instrument not found");
if instrument.asset_class() == AssetClass::SPOT /* or product type Spot */ {
// skip mark price subscription, use ticker data instead
return Ok(());
}
data_engine.subscribe_mark_prices(instrument_id)?; Try / catch
match data_engine.subscribe_mark_prices(instrument_id) {
Err(e) if e.to_string().contains("Mark prices not available for Spot") => {
// fall back to quote/ticker data
}
r => r?,
} Prevention
- Resolve the instrument's product type before subscribing to derivatives-only feeds
- Keep Spot and derivatives instruments in separate subscription paths
- Document which data feeds are venue/product-specific in your strategy config
When it happens
Trigger: Calling subscribe_mark_prices (via DataEngine.subscribe_mark_prices or SubscribeMarkPrices command) with an instrument_id whose symbol suffix maps to Bybit Spot (e.g. BTCUSDT.SBYBIT resolved to Spot).
Common situations: Configuring a strategy that assumes mark prices exist for all instruments; reusing a data pipeline built for perp/futures symbols with Spot symbols; get_product_type_for_instrument returning Spot from the symbol suffix.
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
- Index prices not available for Spot instruments
- WS submit order failed: {e}
- WS cancel order failed: {e}
- WS modify order failed: {e}
- WS setup error channel closed
AI-assisted analysis of nautechsystems/nautilus_trader@18893faf8b (2026-09-08).
Data as JSON: /api/errors/355c4af62547b8ee.
Report an issue: GitHub.