nautechsystems/nautilus_trader · error
{quantity_field} {quantity} must be positive
Error message
{quantity_field} {quantity} must be positive What it means
validate_pending_trade_values checks quantity/price pairs for pending target trades before reconciliation. Trade size must be strictly greater than zero; a zero or negative quantity is rejected with this anyhow error, using the caller-supplied field label.
Source
Thrown at crates/adapters/polymarket/src/execution/reconciliation.rs:418
fn validate_trade_values(
quantity: Decimal,
price: Decimal,
size_precision: u8,
quantity_field: &str,
price_field: &str,
) -> anyhow::Result<Price> {
validate_quantity_evidence(quantity, size_precision, quantity_field, false)?;
validate_historical_price_evidence(price, price_field)
}
fn validate_pending_trade_values(
quantity: Decimal,
price: Decimal,
quantity_field: &str,
price_field: &str,
) -> anyhow::Result<()> {
anyhow::ensure!(
quantity > Decimal::ZERO,
"{quantity_field} {quantity} must be positive"
);
anyhow::ensure!(
price > Decimal::ZERO && price < Decimal::ONE,
"{price_field} {price} must be greater than zero and less than one",
);
Ok(())
}
fn require_trade_timestamp(
ts_event: Option<UnixNanos>,
trade: &PolymarketTradeReport,
) -> anyhow::Result<UnixNanos> {
ts_event.with_context(|| {
format!(
"selected trade {} has invalid match_time {}",
trade.id, trade.match_time,View on GitHub (pinned to 18893faf8b)
Solutions
- Skip orders whose remaining quantity is zero before calling classify_target_trade.
- Clamp or early-return when quantity <= 0 with a debug log instead of feeding it into reconciliation.
- Fix the upstream computation that yields a negative remaining quantity (typically size - filled with inconsistent units).
Example fix
// before
let remaining = total_size - filled; // can be 0 or negative
validate_pending_trade_values(remaining, price, "remaining_size", "price")?;
// after
let remaining = (total_size - filled).max(Decimal::ZERO);
if remaining.is_zero() { return Ok(None); } // skip fully-filled orders
validate_pending_trade_values(remaining, price, "remaining_size", "price")?; Defensive patterns
Strategy: validation
Validate before calling
fn is_positive(q: rust_decimal::Decimal) -> bool { q > rust_decimal::Decimal::ZERO }
if !is_positive(remaining) { return Ok(None); } // skip fully-filled/closed trades Type guard
fn is_valid_pending_qty(q: &rust_decimal::Decimal) -> bool { q.is_sign_positive() && !q.is_zero() } Try / catch
match classify_target_trade(&order, &evidence) {
Err(e) if e.to_string().ends_with("must be positive") => Ok(None), // treat as nothing pending
other => other,
} Prevention
- Filter out fully-filled orders (remaining == 0) before reconciliation
- Use saturating/checked subtraction for remaining-size math to avoid negative quantities
- Sanity-check provider size fields for 0 values on closed markets
When it happens
Trigger: classify_target_trade passes a Decimal quantity <= 0 (e.g. remaining size after fills is 0, or a signed subtraction went negative) into validate_pending_trade_values.
Common situations: Fully-filled orders whose computed remaining quantity reaches 0 and are still fed through reconciliation; signed-quantity bugs producing negative pending sizes; provider size fields parsed as 0 for closed markets.
Understand the failure class
Background: "Must be a positive integer", "Invalid value", "Unsupported": the invalid-argument-value error family, when a library rejects the value you pass — this error's family across 35 libraries.
Related errors
- historical {field} {value} exceeds the maximum representable
- unmapped_in_scope_message("open order", instrument_id, Some(
- unmapped_in_scope_message("position", instrument_id, None, c
- Polymarket market BUY amount {} pUSD truncates to zero at {L
- invalid market-buy price {price}: must satisfy 0 < price < 1
AI-assisted analysis of nautechsystems/nautilus_trader@18893faf8b (2026-09-08).
Data as JSON: /api/errors/11b8766d2d25dd49.
Report an issue: GitHub.