nautechsystems/nautilus_trader · error

Instrument not found in cache

Error message

Instrument {instrument_id} not found in cache

What it means

Raised in `submit_order_internal` (via `submit_order`) when the AX HTTP client cannot return the instrument definition for the order's symbol. The adapter calls `http_client.get_instrument(&symbol)` while preparing an aggressive (marketable) limit order preview, and `ok_or_else` converts the missing instrument into this error. The adapter cannot compute contract quantities or price precision without the instrument definition.

Solutions

  1. Verify the instrument ID's symbol exists on the Architect AX venue and matches AX's symbol conventions.
  2. Confirm the instrument is registered/loadable in the cache before submitting orders (subscribe to the instrument or load it at startup).
  3. Check that the HTTP client points to the intended AX environment (prod vs test) where the instrument is listed.
  4. Ensure the symbol string passed to `get_instrument` is exact (no whitespace, correct casing).
  5. If the instrument was recently listed/delisted, refresh the instrument metadata.

Example fix

// before
let qty = Quantity::from(1);
engine.submit_order(order);  // instrument never loaded for this venue
// after
if client.get_instrument(&symbol).is_none() {
    return Err(anyhow::anyhow!("load or register instrument {symbol} first"));
}
engine.submit_order(order);
Defensive patterns

Strategy: validation

Validate before calling

let symbol = instrument_id.symbol.inner();
if http_client.get_instrument(&symbol).is_none() {
    anyhow::bail!("instrument {instrument_id} unavailable on AX; register or refresh before trading");
}

Try / catch

match engine.submit_order(order) {
    Err(e) if e.to_string().contains("not found in cache") => {
        log::error!("load AX instrument metadata for {} before submitting", order.instrument_id());
    }
    other => other?,
}

Prevention

When it happens

Trigger: Submitting a MARKET (aggressive limit) order for an instrument whose symbol is not resolvable by `get_instrument` on the AX HTTP API: unknown/misspelled symbol, instrument not listed on AX, or the HTTP lookup fails/returns nothing.

Common situations: Order placed on an instrument ID that belongs to a different venue; symbol format mismatch between internal instrument ID and AX's expected symbol; instrument delisted or not yet loaded into the cache; HTTP client misconfigured pointing at wrong environment.

Understand the failure class

Background: 'Could not be found', 'does not exist', 'not found in database': the resource-not-found family when an ID, slug, key, or URI lookup comes back empty — this error's family across 20 libraries.

Related errors


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

Appendix: source

Thrown at crates/adapters/architect_ax/src/execution.rs:255

        let trader_id = self.core.trader_id;
        let emitter = self.emitter.clone();
        let clock = self.clock;

        let http_client = self.http_client.clone();

        self.spawn_task("submit_order", async move {
            // AX emulates market orders with preview-priced IOC limits, so book moves
            // between preview and submission can produce partial fills.
            let (price, submit_time_in_force, submit_post_only) = if order_type
                == OrderType::Market
            {
                let preview_result: anyhow::Result<Price> = async {
                    let symbol = instrument_id.symbol.inner();
                    let ax_side = AxOrderSide::from(order_side);
                    let qty_contracts = quantity_to_contracts(quantity)?;

                    let instrument = http_client.get_instrument(&symbol).ok_or_else(|| {
                        anyhow::anyhow!("Instrument {instrument_id} not found in cache")
                    })?;

                    let request =
                        PreviewAggressiveLimitOrderRequest::new(symbol, qty_contracts, ax_side);
                    let response = http_client
                        .inner
                        .preview_aggressive_limit_order(&request)
                        .await
                        .map_err(|e| {
                            anyhow::anyhow!("Failed to preview aggressive limit order: {e}")
                        })?;

                    if response.remaining_quantity > 0 {
                        log::warn!(
                            "Market order book depth insufficient: \
                             filled_qty={} remaining_qty={} for {instrument_id}",
                            response.filled_quantity,
                            response.remaining_quantity,

View on GitHub (pinned to 18893faf8b)