nautechsystems/nautilus_trader · error · anyhow::Error
instrument ID differs across fill group
Error message
instrument ID differs across fill group
What it means
Same consistency guard family: every fill in the group must share the instrument_id of the first fill. This fires when fills for different instruments were placed in the same group, so a single OrderStatusReport could not represent them.
Source
Thrown at crates/live/src/execution/manager.rs:1279
}
fn create_orphan_fill_order_report(
fills: &[&FillReport],
instrument: &InstrumentAny,
) -> anyhow::Result<OrderStatusReport> {
let Some(first) = fills.first() else {
anyhow::bail!("fill group is empty");
};
let venue_position_id = first
.venue_position_id
.ok_or_else(|| anyhow::anyhow!("venue position ID is missing"))?;
for fill in fills.iter().skip(1) {
anyhow::ensure!(
fill.account_id == first.account_id,
"account ID differs across fill group"
);
anyhow::ensure!(
fill.instrument_id == first.instrument_id,
"instrument ID differs across fill group"
);
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"View on GitHub (pinned to 18893faf8b)
Solutions
- Add instrument_id to the fill grouping key.
- Confirm venue order ID uniqueness semantics and namespace by instrument if needed.
- Check recent changes to reconciliation/grouping code or adapter ID mapping.
- Report as a bug if stock grouping mixes instruments.
Example fix
// before let group_key = fill.venue_order_id; // after let group_key = (fill.instrument_id, fill.venue_order_id);
Defensive patterns
Strategy: validation
Validate before calling
anyhow::ensure!(fills.iter().all(|f| f.instrument_id == fills[0].instrument_id), "mixed instruments in group");
Type guard
fn single_instrument(fills: &[&FillReport]) -> bool { fills.iter().all(|f| f.instrument_id == fills.first().unwrap().instrument_id) } Try / catch
if let Err(e) = create_orphan_fill_order_report(&fills, &instrument) { log::error!("fill group inconsistent: {e}"); return; } Prevention
- Include instrument_id in every fill grouping key
- Namespace venue order IDs by instrument when the venue reuses IDs
- Review grouping-key changes in reconciliation code before deploying
When it happens
Trigger: Fill reports for different instrument_ids sharing the grouping key — usually a grouping key that omits instrument_id, or venue order IDs reused across instruments.
Common situations: Adapters whose order IDs are only unique per instrument (common on some venues); reconciliation batches combining multiple instruments; grouping-key refactors that dropped the instrument component.
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
- venue position ID is missing
- account ID differs across fill group
- {FAILED}: {e}
- Binance Futures position request has unresolved instrument {
- Modify order failed: {e}
AI-assisted analysis of nautechsystems/nautilus_trader@18893faf8b (2026-09-08).
Data as JSON: /api/errors/7ec60e5f06f38744.
Report an issue: GitHub.