nautechsystems/nautilus_trader · error · anyhow::Error

venue order ID differs across fill group

Error message

venue order ID differs across fill group

What it means

During reconciliation, NautilusTrader groups multiple FillReports that belong to the same external (orphan) order and synthesizes a single OrderStatusReport from them via create_orphan_fill_order_report. This ensure! guards the invariant that every fill in the group carries the same venue_order_id; a group whose fills disagree cannot be collapsed into one order report. It is an internal consistency check on venue-reported fill data.

Source

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

        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"
            );
        }

        anyhow::ensure!(

View on GitHub (pinned to 18893faf8b)

Solutions

  1. Check how your venue adapter keys fill groups during reconciliation; fills must be grouped by (account_id, instrument_id, venue_order_id) before reaching create_orphan_fill_order_report.
  2. Inspect the FillReport data from the venue's order/mass status report and verify venue_order_id is populated consistently for all fills of the same order.
  3. Update or pin the adapter crate version so its grouping logic matches the venue's current ID semantics.
  4. If the fills genuinely belong to different orders, ensure they are split into separate groups (or that one is not mislabeled as an orphan fill) instead of merged.

Example fix

// before: grouping fills by position only
let group: Vec<&FillReport> = fills_by_position[position_id].clone();
// after: group by venue order ID as well
let group: Vec<&FillReport> = fills_by_order[&venue_order_id].clone();
Defensive patterns

Strategy: validation

Validate before calling

let venue_order_ids: std::collections::HashSet<_> = fills.iter().map(|f| f.venue_order_id).collect();
assert!(venue_order_ids.len() == 1, "fill group spans multiple venue order IDs: {:?}", venue_order_ids);

Type guard

fn single_venue_order_group(fills: &[&FillReport]) -> bool {
    fills.iter().all(|f| f.venue_order_id == fills[0].venue_order_id)
}

Prevention

When it happens

Trigger: A batch of FillReports passed to create_orphan_fill_order_report (built during generate_order_status_reports / reconciliation from mass status fill reports) contains two fills with identical instrument/account/position grouping keys but different venue_order_id values, so the deduplication keying used to form the group did not match the fills' actual venue_order_id.

Common situations: Venue adapter bugs in fill-report grouping (e.g. grouping by trade ID or position instead of venue order ID); adapter updates after a venue changed its order-ID semantics; manually constructed or replayed reconciliation payloads mixing fills from different orders.

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/e00c3ecd89376322. Report an issue: GitHub.