nautechsystems/nautilus_trader · error

provider venue-leg quantity {} does not match expected quant

Error message

provider venue-leg quantity {} does not match expected quantity {leg_quantity}

What it means

For provider-sourced status reports on multi-leg (neg-risk) orders, the adapter computes the expected per-venue-leg quantity from the cached order via venue_leg_filled_before_and_quantity and requires the venue-reported leg quantity to match. This ensure! fires when the venue leg quantity differs from the quantity derived from the cached order, indicating divergence between local order state and venue state.

Source

Thrown at crates/adapters/polymarket/src/execution/reports.rs:873

                .client_order_id
                .and_then(|id| self.core.cache().order_owned(&id))
                .or_else(|| {
                    self.core
                        .cache()
                        .client_order_id(&report.venue_order_id)
                        .and_then(|id| self.core.cache().order_owned(id))
                });
            let filled_before_leg = if let Some(filled_before) =
                modify_fill_offsets.get(&report.venue_order_id).copied()
            {
                filled_before
            } else if let Some(cached_order) = cached_order.as_ref() {
                let (filled_before, leg_quantity) = venue_leg_filled_before_and_quantity(
                    cached_order,
                    report.venue_order_id,
                    report.quantity.precision,
                )?;
                anyhow::ensure!(
                    report.quantity == leg_quantity,
                    "provider venue-leg quantity {} does not match expected quantity {leg_quantity}",
                    report.quantity,
                );
                report.quantity = cached_order.quantity();
                report.filled_qty = filled_before
                    .checked_add(report.filled_qty)
                    .context("logical filled quantity overflow")?;
                filled_before
            } else {
                Quantity::zero(report.quantity.precision)
            };

            let cached_filled = cached_order.as_ref().map_or_else(
                || Quantity::zero(report.quantity.precision),
                Order::filled_qty,
            );
            let tracked_leg_filled = self

View on GitHub (pinned to 18893faf8b)

Solutions

  1. Reconcile the cache with a full order status refresh from the venue
  2. Verify fills were applied to the cached order (check for dropped fill events)
  3. Check precision passed to venue_leg_filled_before_and_quantity matches the venue
  4. Restart the adapter to rebuild cache from venue state if divergence persists

Example fix

// before
let (filled, leg_qty) = venue_leg_filled_before_and_quantity(cached_order, void_id, wrong_precision)?;
// after
let (filled, leg_qty) = venue_leg_filled_before_and_quantity(
    cached_order, void_id, report.quantity.precision)?; // use venue's own precision
Defensive patterns

Strategy: validation

Validate before calling

let (_, leg_qty) = venue_leg_filled_before_and_quantity(cached_order, void_id, report.quantity.precision)?;
anyhow::ensure!(leg_qty == report.quantity, "cached leg state diverged from venue");

Type guard

fn leg_quantity_consistent(cached: &OrderAny, report: &OrderStatusReport) -> bool {
    venue_leg_filled_before_and_quantity(cached, report.venue_order_id, report.quantity.precision)
        .map(|(_, q)| q == report.quantity)
        .unwrap_or(false)
}

Try / catch

match client.generate_order_status_reports(cmd).await {
    Err(e) if e.to_string().contains("does not match expected quantity") => {
        warn!("cache/venue quantity drift for {} — requesting reconciliation", cmd.venue_order_id);
    }
    other => other?,
}

Prevention

When it happens

Trigger: generate_order_status_reports_impl processes a report for a venue_order_id leg whose cached order yields leg_quantity != report.quantity — typically after partial fills or a replace changed the quantity but the cache leg bookkeeping is stale.

Common situations: Missed fill events so cached filled quantities drifted; replace changed size without cache update; precision mismatch in leg quantity calculation; venue-side manual modification.

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