{"record":{"id":"67ac7454e82aae9a","repo":"nautechsystems/nautilus_trader","slug":"failed-to-create-avg-px-price-e","errorCode":null,"errorMessage":"Failed to create avg_px price: {e}","messagePattern":"Failed to create avg_px price: (.+?)","errorType":"exception","errorClass":"anyhow::Error","httpStatus":null,"severity":"error","filePath":"crates/adapters/interactive_brokers/src/execution/core_updates.rs","lineNumber":956,"sourceCode":"        let mut progress = order_fill_progress.lock();\n        let (previous_filled, previous_notional) = progress\n            .get(&client_order_id)\n            .copied()\n            .unwrap_or((Decimal::ZERO, Decimal::ZERO));\n        let total_notional = filled_decimal * avg_decimal;\n        progress.insert(client_order_id, (filled_decimal, total_notional));\n        drop(progress);\n\n        let fill_delta = filled_decimal - previous_filled;\n        if fill_delta <= Decimal::ZERO || !is_spread_order {\n            return Ok(());\n        }\n\n        let notional_delta = total_notional - previous_notional;\n        let partial_avg_decimal = notional_delta / fill_delta;\n        let partial_avg_px =\n            Price::from_decimal_dp(partial_avg_decimal, instrument.price_precision())\n                .map_err(|e| anyhow::anyhow!(\"Failed to create avg_px price: {e}\"))?;\n\n        pending_combo_fill_avgs\n            .lock()\n            .entry(client_order_id)\n            .or_default()\n            .push_back((fill_delta, partial_avg_px));\n\n        Ok(())\n    }\n\n    pub(super) fn flush_pending_combo_fills(\n        client_order_id: ClientOrderId,\n        pending_combo_fills: &Arc<Mutex<AHashMap<ClientOrderId, VecDeque<PendingComboFill>>>>,\n        pending_combo_fill_avgs: &Arc<Mutex<AHashMap<ClientOrderId, VecDeque<(Decimal, Price)>>>>,\n        order_fill_progress: &Arc<Mutex<AHashMap<ClientOrderId, (Decimal, Decimal)>>>,\n        exec_sender: &tokio::sync::mpsc::UnboundedSender<ExecutionEvent>,\n    ) -> anyhow::Result<()> {\n        let mut combo_fills = pending_combo_fills.lock();","sourceCodeStart":938,"sourceCodeEnd":974,"githubUrl":"https://github.com/nautechsystems/nautilus_trader/blob/18893faf8b356be3320add8de2f861b0b647cf06/crates/adapters/interactive_brokers/src/execution/core_updates.rs#L938-L974","documentation":"For combo (legged) fills, the adapter computes a partial average price Decimal and converts it to a Price via Price::from_decimal_dp. This error wraps any failure of that conversion — typically because the partial average decimal exceeds the instrument's price precision or cannot be represented at that precision.","triggerScenarios":"update_order_avg_price computes partial_avg_decimal = notional_delta / fill_delta and Price::from_decimal_dp(partial_avg_decimal, instrument.price_precision()) fails — e.g. price_precision is 0/invalid or the decimal cannot be rounded to the allowed decimal places.","commonSituations":"Instrument loaded with wrong price_precision from the venue/instrument provider; very small fill deltas producing extreme averages that can't fit the precision.","solutions":["Confirm the instrument definition's price_precision matches the actual IB contract (check the instrument provider data).","Round/quantize partial_avg_decimal to the instrument precision before building the Price.","Guard against fill_delta == 0 or degenerate notional deltas before the division."],"exampleFix":"// before\nlet partial_avg_px =\n    Price::from_decimal_dp(partial_avg_decimal, instrument.price_precision())\n        .map_err(|e| anyhow::anyhow!(\"Failed to create avg_px price: {e}\"))?;\n// after\nlet rounded = partial_avg_decimal\n    .round_dp(u32::from(instrument.price_precision()));\nlet partial_avg_px = Price::from_decimal_dp(rounded, instrument.price_precision())\n    .map_err(|e| anyhow::anyhow!(\"Failed to create avg_px price: {e}\"))?;","handlingStrategy":"validation","validationCode":"// Rust: check precision and divisor before building the Price\nif fill_delta <= Decimal::ZERO {\n    tracing::warn!(\"Zero fill delta; skipping partial avg price\");\n    return Ok(());\n}\nlet dp = u32::from(instrument.price_precision());\nlet rounded = partial_avg_decimal.round_dp(dp);","typeGuard":"fn fits_precision(d: Decimal, precision: u8) -> bool {\n    (d.round_dp(u32::from(precision)) - d).abs() < Decimal::new(1, i64::from(precision))\n}","tryCatchPattern":"let partial_avg_px = match Price::from_decimal_dp(partial_avg_decimal, instrument.price_precision()) {\n    Ok(px) => px,\n    Err(e) => {\n        tracing::error!(\"Partial avg price out of range: {e}\");\n        return Ok(());\n    }\n};","preventionTips":["Confirm instrument price_precision from the instrument provider matches the IB contract","Quantize computed averages to instrument precision before constructing Price","Guard divisions by zero fill deltas in combo-fill logic"],"tags":["price","precision","decimal","instrument-config","rust"],"backgroundTag":"value-out-of-range","analyzedSha":"18893faf8b356be3320add8de2f861b0b647cf06","analyzedAt":"2026-09-08T20:49:34.690Z","contentChangedAt":"2026-09-08T20:49:34.690Z","schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}