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 = selfView on GitHub (pinned to 18893faf8b)
Solutions
- Re-poll the order status; if transient, the next poll may match after venue settles
- Verify quantity conversion when building the promotion payload (precision/scale)
- Check venue UI/API for manual edits to the replacement order
- 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
- Build promotion payloads from the order's Decimal quantity directly; never round via f64
- After a replace, allow a short settle delay before promoting status reports
- Alert on repeated mismatches — they indicate venue-side manual edits or missed events
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
- replacement venue-leg price {:?} does not match signed price
- replacement venue-leg side {:?} does not match logical order
- provider venue-leg quantity {} does not match expected quant
- AX requires whole contract quantities, was {}
- Order quantity must be at least 1 contract
AI-assisted analysis of nautechsystems/nautilus_trader@18893faf8b (2026-09-08).
Data as JSON: /api/errors/a91d93e9119aa0ae.
Report an issue: GitHub.