nautechsystems/nautilus_trader · error

Cannot subscribe for synthetic instrument `OrderBookDepth10`

Error message

Cannot subscribe for synthetic instrument `OrderBookDepth10` data

What it means

subscribe_book_depth10 rejects OrderBookDepth10 subscriptions for synthetic instrument IDs. Depth-10 book data is sourced from a venue data client and cannot exist for a locally computed synthetic instrument, so the engine bails before mutating any subscription state.

Source

Thrown at crates/data/src/engine/mod.rs:3136

        // Validate parent shape BEFORE mutating subscription state so a parse
        // failure leaves the engine bookkeeping unchanged.
        let parent = resolve_parent_components(&cmd.instrument_id, cmd.params.as_ref())?;

        let had_deltas =
            self.has_book_delta_subscription_key(cmd.instrument_id, cmd.client_id, cmd.venue);

        if cmd.managed {
            self.setup_book_updater(&cmd.instrument_id, cmd.book_type, true, parent)?;
        }

        self.increment_book_delta_subscription(cmd.instrument_id, cmd.client_id, cmd.venue);

        Ok(!had_deltas)
    }

    fn subscribe_book_depth10(&mut self, cmd: &SubscribeBookDepth10) -> anyhow::Result<bool> {
        if cmd.instrument_id.is_synthetic() {
            anyhow::bail!("Cannot subscribe for synthetic instrument `OrderBookDepth10` data");
        }

        let parent = resolve_parent_components(&cmd.instrument_id, cmd.params.as_ref())?;
        let had_depth10 =
            self.has_book_depth10_subscription_key(cmd.instrument_id, cmd.client_id, cmd.venue);

        if cmd.managed {
            self.setup_book_updater(&cmd.instrument_id, cmd.book_type, false, parent)?;
        }

        self.increment_book_depth10_subscription(cmd.instrument_id, cmd.client_id, cmd.venue);

        Ok(!had_depth10)
    }

    fn subscribe_book_snapshots(&mut self, cmd: &SubscribeBookSnapshots) -> anyhow::Result<()> {
        if cmd.instrument_id.is_synthetic() {
            anyhow::bail!("Cannot subscribe for synthetic instrument `OrderBookDelta` data");

View on GitHub (pinned to 18893faf8b)

Solutions

  1. Subscribe to OrderBookDepth10 only with real venue instrument IDs
  2. Guard with instrument_id.is_synthetic() before issuing the depth10 subscription
  3. Use synthetic instrument data APIs for computed prices rather than book depth
  4. Audit config files for synthetic '=' ID notation in book-depth instrument fields

Example fix

// before
engine.subscribe_book_depth10(SubscribeBookDepth10::new(synthetic_id, client_id, venue));
// after
if !synthetic_id.is_synthetic() {
    engine.subscribe_book_depth10(SubscribeBookDepth10::new(synthetic_id, client_id, venue));
}
Defensive patterns

Strategy: validation

Validate before calling

if instrument_id.is_synthetic() {
    return Ok(()); // depth10 data only exists for venue instruments
}

Type guard

fn is_book_capable(id: &InstrumentId) -> bool {
    !id.is_synthetic()
}

Try / catch

if let Err(e) = engine.subscribe_book_depth10(&cmd) {
    if e.to_string().contains("synthetic") { log::error!("invalid depth10 target: {e}"); }
    else { return Err(e.into()); }
}

Prevention

When it happens

Trigger: Calling DataEngine.subscribe_book_depth10 with a cmd.instrument_id where is_synthetic() is true — typically a SyntheticInstrument-generated ID passed into a depth subscription command.

Common situations: Configuring depth-10 book feeds with a synthetic instrument ID by mistake; templated strategy configs that substitute the traded instrument without filtering synthetic IDs.

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