nautechsystems/nautilus_trader · error

instrument metadata ID {} does not match {instrument_id}

Error message

instrument metadata ID {} does not match {instrument_id}

What it means

`resolve_precision` looks up cached instrument metadata for an order symbol to recover price/size precision during recovery reconciliation. Beyond a missing entry, it enforces an internal invariant with `anyhow::ensure!`: the cached instrument's ID must equal the instrument ID constructed from the symbol and product type (`format_instrument_id`). A mismatch means the cache is keyed by symbol but holds an instrument belonging to a different market/product, so precisions cannot be trusted and the open-order report fails (triggering another recovery attempt).

Source

Thrown at crates/adapters/binance/src/futures/websocket/streams/recovery.rs:444

    if !open_ok && !algo_ok {
        anyhow::bail!("recovery reconcile failed: both REST queries returned errors");
    }

    log::info!("Recovery reconcile emitted {emitted} OrderStatusReport(s)");
    Ok(())
}

fn resolve_precision(
    instruments: &DashMap<ustr::Ustr, crate::futures::http::client::BinanceFuturesInstrument>,
    symbol_ustr: &ustr::Ustr,
    product_type: BinanceProductType,
) -> anyhow::Result<(InstrumentId, u8, u8)> {
    let instrument_id = format_instrument_id(symbol_ustr, product_type);
    let instrument = instruments
        .get(symbol_ustr)
        .map(|instrument| instrument.value().clone())
        .with_context(|| format!("missing instrument metadata for {instrument_id}"))?;
    anyhow::ensure!(
        instrument.id() == instrument_id,
        "instrument metadata ID {} does not match {instrument_id}",
        instrument.id()
    );
    let (price_precision, size_precision) = instrument.precisions()?;

    Ok((instrument_id, price_precision, size_precision))
}

#[cfg(test)]
mod tests {
    use std::str::FromStr;

    use axum::{
        Json, Router,
        extract::State,
        http::{StatusCode, Uri},
        response::{IntoResponse, Response},

View on GitHub (pinned to 18893faf8b)

Solutions

  1. Check the log: compare the cached instrument ID (first `{}`) against the expected ID; identify which product type's cache was loaded.
  2. Rebuild the instruments cache from the correct product type's exchangeInfo before recovery.
  3. Ensure the cache key includes product type (or use separate maps for USDM/COINM) so symbols cannot collide.
  4. Verify `format_instrument_id` and the cache population path use identical symbol normalization (case, suffixes).

Example fix

// before
anyhow::ensure!(
    instrument.id() == instrument_id,
    "instrument metadata ID {} does not match {instrument_id}",
    instrument.id()
);
// after (fix the cache keying so the invariant holds)
let key = (symbol_ustr, product_type); // key instruments by symbol AND product type
let instrument = instruments.get(&key)...;
Defensive patterns

Strategy: validation

Validate before calling

// Rust: verify cache consistency before recovery
fn cache_consistent(instruments: &DashMap<Ustr, AnyInstrument>, product: ProductType) -> bool {
    instruments.iter().all(|e| {
        let expected = format_instrument_id(e.key(), product);
        e.value().id() == expected
    })
}

Prevention

When it happens

Trigger: `emit_open_order_reports` resolves precision for a returned open order; the instruments cache contains an entry for the symbol whose `instrument.id()` differs from `format_instrument_id(symbol, product_type)` — e.g. a USDT-M instrument cached under a symbol also used by COIN-M, or a stale cache built with a different product type.

Common situations: Mixed USDT-M/COIN-M setups where the instruments map was populated from the wrong product's exchange info; symbol reuse across markets (e.g. same base asset on both); cache not invalidated after switching product type.

Understand the failure class

Background: "This is a bug, please report it": internal invariant violations, unreachable panics, and SNH errors explained — this error's family across 47 libraries.

Related errors


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