nautechsystems/nautilus_trader · error · anyhow::Error

venue position ID differs across fill group

Error message

venue position ID differs across fill group

What it means

A synthesized OrderStatusReport for an orphan fill group must resolve to one position. This ensure! checks that all fills in the group report the same venue_position_id (earlier code already bail!s if it is missing entirely); differing position IDs mean the group spans multiple positions and cannot be aggregated into one order report.

Source

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

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

View on GitHub (pinned to 18893faf8b)

Solutions

  1. Ensure the adapter's account configuration (netting vs hedging) matches the actual venue account mode so fills map to a single position ID per order.
  2. Group fills by venue_position_id as part of the key so each group has one consistent position ID.
  3. Check that venue_position_id is parsed from the venue's fill report rather than derived inconsistently per fill.
  4. Re-run reconciliation after correcting account mode / position ID derivation so stale groups are rebuilt from fresh venue reports.

Example fix

// before: group keyed without position
let key = (account_id, venue_order_id);
// after: require a single position ID per group
let key = (account_id, venue_order_id, fill.venue_position_id?);
Defensive patterns

Strategy: validation

Validate before calling

let pos_ids: std::collections::HashSet<_> = fills.iter().map(|f| f.venue_position_id).collect();
assert!(pos_ids.len() == 1 && pos_ids.iter().all(|p| p.is_some()), "fill group has missing or mixed venue position IDs: {:?}", pos_ids);

Type guard

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

Prevention

When it happens

Trigger: FillReports grouped together share order/account/instrument keys but their venue_position_id values differ — e.g. fills that were assigned to different OMS positions by the venue, or None vs Some mismatches that slipped past grouping.

Common situations: Netting vs hedging account-mode mismatches between the venue account and the Nautilus reconciliation config; venue splitting one order's fills across positions after account mode changes; adapter changes to position-ID derivation between versions.

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