nautechsystems/nautilus_trader · error

replacement venue-leg quantity {} does not match signed quan

Error message

replacement venue-leg quantity {} does not match signed quantity {}

What it means

During pending-modification (replace) promotion in generate_order_status_reports_impl, the report fetched for the replacement venue leg must have exactly the quantity that was signed for the replacement. This ensure! fires when the venue reports a different leg quantity than promotion.leg_quantity, meaning venue state diverged from what the adapter signed/submitted.

Source

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

        )?;

        let mut modify_fill_offsets = AHashMap::new();
        let mut rejected_replacements = AHashSet::new();

        for report in &mut reports {
            let promotion = self
                .ws_dispatch_state
                .lock()
                .pending_modify_promotion(report.venue_order_id);
            let Some(promotion) = promotion else {
                continue;
            };

            let context = self
                .order_contexts
                .get(&promotion.old_venue_order_id)
                .context("pending modification has no old-leg context")?;
            anyhow::ensure!(
                report.quantity == promotion.leg_quantity,
                "replacement venue-leg quantity {} does not match signed quantity {}",
                report.quantity,
                promotion.leg_quantity,
            );
            anyhow::ensure!(
                report.price == Some(promotion.price),
                "replacement venue-leg price {:?} does not match signed price {}",
                report.price,
                promotion.price,
            );
            anyhow::ensure!(
                report.order_side == Some(context.identity.order_side),
                "replacement venue-leg side {:?} does not match logical order side {}",
                report.order_side,
                context.identity.order_side,
            );
            let cached_order = self

View on GitHub (pinned to 18893faf8b)

Solutions

  1. Re-poll the order status; if transient, the next poll may match after venue settles
  2. Verify quantity conversion when building the promotion payload (precision/scale)
  3. Check venue UI/API for manual edits to the replacement order
  4. Log and inspect promotion.leg_quantity vs venue response to find the divergence source

Example fix

// before
let promotion = sign_replacement(order, qty_as_f64_rounded)?; // rounding drifted
// after
let promotion = sign_replacement(order, order.quantity())?; // exact Decimal from order
Defensive patterns

Strategy: validation

Validate before calling

let signed_qty = promotion.leg_quantity;
anyhow::ensure!(signed_qty == order.quantity(), "promotion quantity must match logical order quantity");

Type guard

fn promotion_quantity_valid(promotion: &Promotion, report: &OrderStatusReport) -> bool {
    report.quantity == promotion.leg_quantity
}

Try / catch

match reports.iter().find(|r| r.venue_order_id == new_void) {
    Some(r) if r.quantity != promotion.leg_quantity => warn!("venue diverged from signed replace; re-poll"),
    _ => {},
}

Prevention

When it happens

Trigger: A pending modification is promoted to a real order status report, and the venue's returned report.quantity differs from the quantity captured in the signed promotion payload.

Common situations: Venue partially filled or amended the replacement order before the poll; race between submit of replacement and status poll; adapter bug in quantity unit conversion (e.g. lots vs raw) when building the promotion.

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