nautechsystems/nautilus_trader · error
Pending position quantity overflow
Error message
Pending position quantity overflow
What it means
When computing a position's quantity for an order (used to decide whether the order closes or opens the position), the matching engine starts from the position's current quantity and checked-adds the quantity_change of every pending fill belonging to that position. If the accumulated Decimal overflows its maximum precision/width, the engine raises this error instead of producing a wrong signed quantity.
Source
Thrown at crates/execution/src/matching_engine/mod.rs:5089
}
fn position_quantity_remaining(
&mut self,
order: &OrderAny,
position: &Position,
) -> anyhow::Result<Quantity> {
self.purge_applied_fills();
let mut quantity = match position.side {
PositionSide::Long => position.quantity.as_decimal(),
PositionSide::Short => -position.quantity.as_decimal(),
PositionSide::Flat => Decimal::ZERO,
};
for fill in self.pending_fills.values() {
if fill.position_id == Some(position.id) {
quantity = quantity
.checked_add(fill.quantity_change)
.ok_or_else(|| anyhow::anyhow!("Pending position quantity overflow"))?;
}
}
if (order.is_buy() && quantity >= Decimal::ZERO)
|| (order.is_sell() && quantity <= Decimal::ZERO)
{
return Ok(Quantity::zero(position.quantity.precision));
}
Ok(Quantity::from_decimal_dp(
quantity.abs(),
position.quantity.precision,
)?)
}
fn purge_applied_fills(&mut self) {
let cache = self.cache.borrow();
self.pending_fills.retain(|trade_id, fill| {
fill.position_id = fillView on GitHub (pinned to 18893faf8b)
Solutions
- Inspect pending_fills for the position and confirm they are being consumed/drained after each match cycle.
- Reduce order quantity or precision so accumulated quantities fit within the Decimal max supported (max ~18-20 digits with configured precision).
- Check for logic that re-queues the same fill repeatedly (e.g. reduce-only or OCO handling) and fix the duplication.
- Sanitize instrument quantity/precision configuration so position quantity plus pending fills stays in representable range.
Example fix
// before: accumulating pending fills without bound
let mut quantity = position.quantity();
for fill in pending_fills.values() { quantity = quantity.checked_add(fill.quantity_change).expect("overflow"); }
// after: cap/validate incoming order quantity against representable range
assert!(order.quantity() <= max_representable_qty(instrument), "quantity too large");
let mut quantity = position.quantity(); Defensive patterns
Strategy: validation
Validate before calling
// keep order quantities within a range that survives accumulation with pending fills
let max_qty = Decimal::from_str("999999999999999999")?; // leave headroom below Decimal max
assert!(order.quantity() <= max_qty, "order quantity risks position quantity overflow"); Try / catch
match engine_result {
Err(e) if e.to_string().contains("Pending position quantity overflow") => {
log::error!("quantity overflow computing position for {}: {e}", order.client_order_id());
// cancel the order and investigate pending_fills accumulation
}
other => other,
} Prevention
- Use realistic quantity magnitudes and instrument precision in backtests.
- Verify pending_fills are drained each match cycle when writing custom order handling.
- Sanity-check instrument size precision in config before large runs.
When it happens
Trigger: Summing position.quantity with many pending fills' quantity_change values whose total exceeds the Decimal max (e.g. extremely large order quantities combined with high precision, or a runaway loop creating unbounded pending fills against one position).
Common situations: Backtests with unrealistic quantity magnitudes or very high price precision instruments; a bug causing pending_fills to accumulate without being drained; OCO/contingent logic repeatedly re-adding fills for the same position.
Understand the failure class
Background: "value must be between 0 and 1" / "out of range" / "must not be negative" errors: fixing range-validation failures across open-source libraries — this error's family across 42 libraries.
Related errors
- Reduce-only quantity overflow for order {client_order_id}
- Venue order ID counter exhausted
- OUO quantity overflow for order {client_order_id}
- Matching engine not found for instrument {order_instrument_i
- Matching engine not found for instrument {instrument_id}
AI-assisted analysis of nautechsystems/nautilus_trader@18893faf8b (2026-09-08).
Data as JSON: /api/errors/1bb2fc85597e21ec.
Report an issue: GitHub.