nautechsystems/nautilus_trader · error · anyhow::Error

instrument metadata does not match fill group

Error message

instrument metadata does not match fill group

What it means

create_orphan_fill_order_report receives the InstrumentAny whose metadata (precision, size precision, etc.) will be used to build the synthetic OrderStatusReport. This ensure! verifies that instrument.id() matches the instrument_id carried by the fill group; a mismatch means the wrong instrument definition was looked up for these fills, so the report cannot be constructed safely.

Source

Thrown at crates/live/src/execution/manager.rs:1301

            anyhow::ensure!(
                fill.venue_order_id == first.venue_order_id,
                "venue order ID differs across fill group"
            );
            anyhow::ensure!(
                fill.client_order_id == first.client_order_id,
                "client order ID differs across fill group"
            );
            anyhow::ensure!(
                fill.order_side == first.order_side,
                "order side differs across fill group"
            );
            anyhow::ensure!(
                fill.venue_position_id == first.venue_position_id,
                "venue position ID differs across fill group"
            );
        }

        anyhow::ensure!(
            first.instrument_id == instrument.id(),
            "instrument metadata does not match fill group"
        );

        let (quantity, notional) = fills.iter().try_fold(
            (Decimal::ZERO, Decimal::ZERO),
            |(quantity, notional), fill| {
                let fill_quantity = fill.last_qty.as_decimal();
                let quantity = quantity.checked_add(fill_quantity).ok_or_else(|| {
                    anyhow::anyhow!("fill quantity overflow while aggregating fill group")
                })?;

                let fill_notional = fill_quantity
                    .checked_mul(fill.last_px.as_decimal())
                    .ok_or_else(|| {
                        anyhow::anyhow!("fill notional overflow while aggregating fill group")
                    })?;

View on GitHub (pinned to 18893faf8b)

Solutions

  1. Verify the instrument lookup used for reconciliation resolves exactly the fill's instrument_id (compare instrument.id() with fill.instrument_id before calling).
  2. Reload the instrument definitions from the venue so cached instrument IDs match the IDs in current fill reports.
  3. Check for symbol aliasing or venue-name mismatches between the adapter's instrument IDs and those in your cache/catalog.
  4. If loading instruments from a saved catalog, regenerate them for the current venue and version instead of reusing stale files.

Example fix

// before: fetched by assumed symbol
let instrument = cache.instrument(&assumed_id)?;
// after: resolve by the fill's own instrument ID
let instrument = cache.instrument(&first.instrument_id)
    .ok_or_else(|| anyhow::anyhow!("instrument {} not in cache", first.instrument_id))?;
Defensive patterns

Strategy: validation

Validate before calling

assert_eq!(instrument.id(), first.instrument_id, "instrument {} does not match fill group instrument {}", instrument.id(), first.instrument_id);

Type guard

fn instrument_matches(instrument: &InstrumentAny, first: &FillReport) -> bool {
    instrument.id() == first.instrument_id
}

Prevention

When it happens

Trigger: During reconciliation, the instrument passed to create_orphan_fill_order_report was resolved from the cache or reconciliation_instrument_ids by a different instrument_id than the one on the FillReport group — e.g. a stale/aliased instrument definition or a cache keyed by the wrong ID.

Common situations: Instrument definitions reloaded with a changed symbol/venue after a venue rename; loading instruments for the wrong venue into the cache; symbol aliasing differences (e.g. perpetual suffixes) between the adapter and the cached instrument; replaying historical data with old instrument IDs.

Understand the failure class

Background: "Must be a positive integer", "Invalid value", "Unsupported": the invalid-argument-value error family, when a library rejects the value you pass — this error's family across 35 libraries.

Related errors


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