nautechsystems/nautilus_trader · error · anyhow::Error
Failed to convert filled qty to Decimal: {filled}
Error message
Failed to convert filled qty to Decimal: {filled} What it means
The adapter converts the IB-reported filled quantity (an f64) into a Decimal using from_f64_retain, which returns None for NaN, infinite, or otherwise non-representable values. When the filled quantity from an IB execution report is not a finite finite number, this error is thrown so no bogus fill progress is recorded.
Source
Thrown at crates/adapters/interactive_brokers/src/execution/core_updates.rs:933
order_fill_progress: &Arc<Mutex<AHashMap<ClientOrderId, (Decimal, Decimal)>>>,
) -> anyhow::Result<()> {
let is_spread_order = is_spread_instrument_id(instrument_id);
if filled <= 0.0 || !parse::should_use_avg_fill_price(avg_fill_price, instrument_id) {
return Ok(());
}
let Some(instrument) = instrument_provider.find(instrument_id) else {
return Ok(());
};
let price_magnifier = instrument_provider.get_price_magnifier(instrument_id) as f64;
let converted_avg_price = avg_fill_price * price_magnifier;
let avg_px = Price::new(converted_avg_price, instrument.price_precision());
order_avg_prices.lock().insert(client_order_id, avg_px);
let filled_decimal = Decimal::from_f64_retain(filled)
.ok_or_else(|| anyhow::anyhow!("Failed to convert filled qty to Decimal: {filled}"))?;
let avg_decimal = Decimal::from_f64_retain(converted_avg_price).ok_or_else(|| {
anyhow::anyhow!("Failed to convert avg fill price to Decimal: {converted_avg_price}")
})?;
let mut progress = order_fill_progress.lock();
let (previous_filled, previous_notional) = progress
.get(&client_order_id)
.copied()
.unwrap_or((Decimal::ZERO, Decimal::ZERO));
let total_notional = filled_decimal * avg_decimal;
progress.insert(client_order_id, (filled_decimal, total_notional));
drop(progress);
let fill_delta = filled_decimal - previous_filled;
if fill_delta <= Decimal::ZERO || !is_spread_order {
return Ok(());
}
View on GitHub (pinned to 18893faf8b)
Solutions
- Validate that the filled quantity is finite before calling update_order_avg_price, and skip/quote the update otherwise.
- Check the IB execution report data for NaN/inf fields; upgrade or fix the ibapi parsing if it emits sentinel values.
- Log the raw execution data when this occurs to identify the upstream message producing the bad quantity.
Example fix
// before
let filled_decimal = Decimal::from_f64_retain(filled)
.ok_or_else(|| anyhow::anyhow!("Failed to convert filled qty to Decimal: {filled}"))?;
// after
if !filled.is_finite() || filled < 0.0 {
tracing::warn!("Skipping avg price update with invalid filled qty: {filled}");
return Ok(());
}
let filled_decimal = Decimal::from_f64_retain(filled)
.ok_or_else(|| anyhow::anyhow!("Failed to convert filled qty to Decimal: {filled}"))?; Defensive patterns
Strategy: validation
Validate before calling
// Rust: validate the IB-reported fill quantity before conversion
fn valid_filled_qty(filled: f64) -> bool {
filled.is_finite() && filled >= 0.0
} Type guard
fn is_finite_positive(x: f64) -> bool {
x.is_finite() && x > 0.0
} Try / catch
let filled_decimal = match Decimal::from_f64_retain(filled) {
Some(d) => d,
None => {
tracing::error!("Invalid filled qty {filled}; skipping avg price update");
return Ok(());
}
}; Prevention
- Always check f64.is_finite() on quantities and prices coming from venue callbacks
- Log raw IB execution reports to catch sentinel NaN values early
- Pin and test against the ibapi version you deploy so parsing changes are caught
When it happens
Trigger: update_order_avg_price is called with filled = NaN or +/-inf (from ibapi::OrderData fills or division in the combo-fill path), so Decimal::from_f64_retain(filled) returns None.
Common situations: Malformed or placeholder values in IB execution/commission reports; downstream arithmetic producing inf (e.g. division by zero fill delta) passed back into this function.
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
- Failed to convert avg fill price to Decimal: {converted_avg_
- Invalid quote rate for pair {pair}, was {value}
- {e}
- Unsupported order type: {order_type:?}
- Unknown IB security type: {value}
AI-assisted analysis of nautechsystems/nautilus_trader@18893faf8b (2026-09-08).
Data as JSON: /api/errors/ba655b1fdbc892aa.
Report an issue: GitHub.