nautechsystems/nautilus_trader · error
venue-leg fills cannot be represented exactly
Error message
venue-leg fills cannot be represented exactly
What it means
After computing the venue-leg filled Decimal, it is converted to a Quantity at the order's size_precision. If the value cannot be represented exactly at that precision (Quantity::from_decimal_dp rounds/fails), the subsequent equality check between the Quantity and the original Decimal fails, raising this error to avoid silently rounding fill data.
Source
Thrown at crates/adapters/polymarket/src/execution/reconciliation.rs:81
) -> anyhow::Result<(Quantity, Quantity)> {
let mut filled = Decimal::ZERO;
for event in order.events() {
match event {
OrderEventAny::Filled(event) if event.venue_order_id == venue_order_id => {
filled += event.last_qty.as_decimal();
}
OrderEventAny::FillVoided(event) if event.venue_order_id == venue_order_id => {
filled -= event.voided_qty.as_decimal();
}
_ => {}
}
}
anyhow::ensure!(filled >= Decimal::ZERO, "venue-leg fills are negative");
let current_leg_filled = Quantity::from_decimal_dp(filled, size_precision)
.context("venue-leg fills exceed quantity precision")?;
anyhow::ensure!(
current_leg_filled.as_decimal() == filled,
"venue-leg fills cannot be represented exactly"
);
let filled_before = order
.filled_qty()
.checked_sub(current_leg_filled)
.context("current venue-leg fills exceed cumulative fills")?;
let leg_quantity = order
.quantity()
.checked_sub(filled_before)
.context("fills before current venue leg exceed logical quantity")?;
Ok((filled_before, leg_quantity))
}
/// Shared context for trade-to-fill-report conversion.
pub(crate) struct FillContext<'a> {
pub account_id: AccountId,
pub user_address: &'a str,View on GitHub (pinned to 18893faf8b)
Solutions
- Align the instrument's size_precision with the venue's actual fill size increments.
- Log the raw filled Decimal and compare with the order's size_precision to confirm the mismatch.
- Round venue fills to the instrument's tick size at ingestion so sums remain exactly representable.
Example fix
// before let size_precision = instrument.size_precision(); // 2 dp let qty = Quantity::from_decimal_dp(filled, size_precision)?; // filled has 4 dp // after let size_precision = 4; // match venue fill increments let qty = Quantity::from_decimal_dp(filled, size_precision)?;
Defensive patterns
Strategy: validation
Validate before calling
let dp = filled.scale();
if dp as u32 > size_precision { return Err(anyhow!("fill precision {dp} exceeds instrument precision {size_precision}")); } Type guard
fn fits_precision(d: Decimal, precision: u8) -> bool { (d.scale() as u32) <= precision as u32 } Try / catch
match Quantity::from_decimal_dp(filled, size_precision) {
Ok(q) => q,
Err(_) => { log::warn!("rounding fill {filled} to precision {size_precision}"); Quantity::from_decimal_dp(filled.round_dp(size_precision), size_precision)? }
} Prevention
- Keep instrument size_precision in sync with venue fill increments
- Round venue fills to tick size at ingestion
- Re-sync instrument definitions on venue updates
When it happens
Trigger: Reconstructing fills (via load_orders_from_cache, query_order_command, generate_order_status_report(s)_impl) where summed event quantities carry more decimal places than the order's size_precision — e.g. partial fills with 4 dp against a 2 dp instrument definition.
Common situations: Instrument size_precision misconfigured vs the venue's actual fill increments; manual/odd lot fills from the venue exceeding the declared precision; stale instrument definitions after a venue change.
Understand the failure class
Background: Type mismatch errors: IllegalArgumentException, TypeError and type guards across 150 open-source libraries — this error's family across 150 libraries.
Related errors
- venue-leg fills are negative
- Instrument not found in cache: {symbol}
- Binance Futures position request has unresolved instrument {
- Modify order failed: {e}
- provider venue order {} is not owned by the account
AI-assisted analysis of nautechsystems/nautilus_trader@18893faf8b (2026-09-08).
Data as JSON: /api/errors/f136f68285c54d34.
Report an issue: GitHub.