nautechsystems/nautilus_trader · error · anyhow::Error
failed to resolve positive quantity for current order
Error message
failed to resolve positive quantity for current order {} (order_type={:?}, persistence_type={:?}, price_size={}, bsp_liability={}, size_matched={}, size_remaining={}, size_cancelled={}, size_lapsed={}, size_voided={}) What it means
When parsing a Betfair current-order report, no positive quantity could be derived from the order's fields (order type, price/size, BSP liability, matched/remaining/cancelled/lapsed/voided sizes). The library throws via anyhow::ensure! because downstream execution/reconciliation logic requires a strictly positive quantity.
Solutions
- Skip orders with all-zero size fields instead of querying their status, or filter them in the caller.
- Check the order's order_type; ensure SP/liability orders carry bsp_liability > 0 in the report.
- Log the full order payload and verify Betfair returned real values (no missing size fields).
- If this occurs for legitimate states, handle a zero quantity as a terminal/no-op order in reconciliation before calling parse.
Example fix
// before
let report = client.query_order(&bet_id).await?;
// after
let report = client.query_order(&bet_id).await?;
if report.size_cancelled + report.size_lapsed + report.size_voided > Decimal::ZERO
&& report.size_matched == Decimal::ZERO {
return Ok(None); // never-matched terminal order has no resolvable quantity
} Defensive patterns
Strategy: validation
Validate before calling
fn has_resolvable_qty(o: &CurrentOrder) -> bool {
o.bsp_liability > Decimal::ZERO
|| o.size_matched > Decimal::ZERO
|| o.size_remaining > Decimal::ZERO
} Try / catch
match client.query_order(&bet_id).await {
Ok(r) => r,
Err(e) if e.to_string().contains("failed to resolve positive quantity") => {
log::warn!("order {bet_id} has no resolvable quantity; treating as terminal");
Default::default()
}
Err(e) => return Err(e.into()),
} Prevention
- Skip orders with all-zero size fields before querying their status.
- Reconcile never-matched cancelled/lapsed orders as terminal without quantity resolution.
- Log raw Betfair order payloads to detect SP orders missing bsp_liability.
When it happens
Trigger: query_order or fetch_order_status_reports_snapshot_http receives a current order whose resolved lifecycle quantity is zero or negative and which is not a liability-based order (e.g. market-on-close) with bsp_liability > 0.
Common situations: Fully voided or fully lapsed orders without recorded fills; placeholder BET_DELAY-style orders with size fields all zero; orders whose order_type the quantity resolver does not recognize; Betfair returning reports for orders cancelled before matching.
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
- failed to resolve positive quantity for stream order update
- AX requires whole contract quantities, was
- Cannot extract market ID from
- Cannot extract selection ID from
- Failed to convert quote-to-base quantity for ord_id=
AI-assisted analysis of nautechsystems/nautilus_trader@18893faf8b (2026-09-08).
Data as JSON: /api/errors/4ce4821a8db55d72.
Report an issue: GitHub.
Appendix: source
Thrown at crates/adapters/betfair/src/http/parse.rs:85
OrderStatus::Voided
} else {
resolve_order_status(order.status, size_matched, size_closed)
};
// Prefer lifecycle sum when price_size.size is zero. Use bsp_liability for
// on-close orders that report liability without stake/size.
let total_size = order.price_size.size;
let lifecycle_qty = size_matched + size_remaining + size_cancelled + size_lapsed + size_voided;
let qty = if total_size > Decimal::ZERO {
total_size
} else if lifecycle_qty > Decimal::ZERO {
lifecycle_qty
} else if uses_liability_based_quantity(order) && order.bsp_liability > Decimal::ZERO {
order.bsp_liability
} else {
Decimal::ZERO
};
anyhow::ensure!(
qty > Decimal::ZERO,
"failed to resolve positive quantity for current order {} \
(order_type={:?}, persistence_type={:?}, price_size={}, bsp_liability={}, \
size_matched={}, size_remaining={}, size_cancelled={}, size_lapsed={}, size_voided={})",
order.bet_id,
order.order_type,
order.persistence_type,
order.price_size.size,
order.bsp_liability,
size_matched,
size_remaining,
size_cancelled,
size_lapsed,
size_voided,
);
let quantity = parse_betfair_quantity(qty)?;
let filled_qty = parse_betfair_quantity(size_matched)?;
View on GitHub (pinned to 18893faf8b)