nautechsystems/nautilus_trader · error · InstrumentLookupError

InstrumentLookupError::not_found(instrument_id)

Error message

InstrumentLookupError::not_found(instrument_id)

What it means

subscribe_bars requires the bar subscription's instrument to already exist in the client's local instruments cache. If subscription.bar_type.instrument_id() is not present, it fails with InstrumentLookupError::not_found, meaning the instrument must be loaded/added before bars can be subscribed.

Source

Thrown at crates/adapters/coinbase/src/data/mod.rs:663

            was_empty
        };

        if was_empty {
            let ws = self.ws_client.clone();
            self.spawn_command(async move {
                if let Err(e) = ws.subscribe(CoinbaseWsChannel::Status, &[]).await {
                    log::error!("Failed to subscribe to status channel: {e:?}");
                }
            });
        }
        Ok(())
    }

    fn subscribe_bars(&mut self, subscription: SubscribeBars) -> anyhow::Result<()> {
        let instrument_id = subscription.bar_type.instrument_id();

        if !self.instruments.contains_key(&instrument_id) {
            anyhow::bail!(InstrumentLookupError::not_found(instrument_id));
        }

        let bar_type = subscription.bar_type;
        let subscribed_id = Self::product_id(instrument_id);
        let wire_id = self.resolve_wire_product_id(subscribed_id);
        if wire_id != subscribed_id {
            self.ws_client
                .register_subscription_alias(wire_id, subscribed_id);
        }
        let key = wire_id.to_string();

        // Register on the original client so the bar type persists across clones
        self.ws_client.register_bar_type(key.clone(), bar_type);

        let mut ws = self.ws_client.clone();

        self.spawn_command(async move {
            ws.add_bar_type(key, bar_type).await;

View on GitHub (pinned to 18893faf8b)

Solutions

  1. Load the instrument first (include it in the instrument provider config / call add_instrument) before subscribing to bars
  2. Verify the instrument_id string matches a Coinbase product exactly (e.g. BTC-USD)
  3. Ensure instruments are loaded during connect before any data subscriptions are issued
  4. Check resolve_wire_product_id mapping if using mapped wire product IDs

Example fix

// before
client.subscribe_bars(bars_cmd)?; // instrument never loaded

// after
assert!(client.instruments().contains_key(&instrument_id));
client.subscribe_bars(bars_cmd)?;
Defensive patterns

Strategy: validation

Validate before calling

if !client.instruments_cache_contains(&subscription.bar_type.instrument_id()) {
    return Err(anyhow!("load instrument before subscribing to bars"));
}

Prevention

When it happens

Trigger: Subscribing to bars for an instrument_id that was never added via instrument provider loading (e.g. a typo'd symbol like 'BTC-USDT.PERP' when only 'BTC-USD' is loaded, or subscribing before connect loaded instruments).

Common situations: Config symbol mismatch with the loaded instrument provider; subscribing immediately after client construction without waiting for instrument load; requesting bars for a product Coinbase does not list.

Understand the failure class

Background: Record Not Found Errors: "not found", RecordNotFound, and "was not found" — what they mean and how to fix them — this error's family across 28 libraries.

Related errors


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