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
- Verify the instrument lookup used for reconciliation resolves exactly the fill's instrument_id (compare instrument.id() with fill.instrument_id before calling).
- Reload the instrument definitions from the venue so cached instrument IDs match the IDs in current fill reports.
- Check for symbol aliasing or venue-name mismatches between the adapter's instrument IDs and those in your cache/catalog.
- 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
- Resolve instruments by the FillReport's instrument_id, never by an assumed or aliased symbol.
- Reload instrument definitions from the venue whenever symbols, venue names, or adapter versions change.
- Assert instrument.id() == fill.instrument_id at the boundary where instruments are loaded into the cache.
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
- Binance Futures position has unresolved instrument {instrume
- Binance Futures position request has unresolved instrument {
- Modify order failed: {e}
- InstrumentLookupError::not_found(instrument_id)
- Instrument {instrument_id} not found and `auto_load_missing_
AI-assisted analysis of nautechsystems/nautilus_trader@18893faf8b (2026-09-08).
Data as JSON: /api/errors/45f4d299d85475df.
Report an issue: GitHub.