{"record":{"id":"c99888b086bd0600","repo":"nautechsystems/nautilus_trader","slug":"quantity-for-currency-exceeds-money-raw-bounds","errorCode":null,"errorMessage":"quantity for {currency} exceeds Money raw bounds","messagePattern":"quantity for (.+?) exceeds Money raw bounds","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"crates/portfolio/src/manager.rs","lineNumber":1443,"sourceCode":"            let scale = 10_i128.pow(u32::from(target_precision - source_precision));\n            raw.checked_mul(scale).ok_or_else(|| {\n                anyhow::anyhow!(\"quantity for {currency} overflowed while increasing raw scale\")\n            })?\n        }\n        Ordering::Greater => {\n            let scale = 10_i128.pow(u32::from(source_precision - target_precision));\n            anyhow::ensure!(\n                raw % scale == 0,\n                \"quantity for {currency} loses precision when decreasing raw scale\"\n            );\n            raw / scale\n        }\n        Ordering::Equal => raw,\n    };\n    check_fixed_raw_i128(raw, currency.precision)?;\n    let raw: MoneyRaw = raw\n        .try_into()\n        .map_err(|_| anyhow::anyhow!(\"quantity for {currency} exceeds Money raw bounds\"))?;\n\n    Money::from_raw_checked(raw, currency).map_err(Into::into)\n}\n\nfn reservation_precisions_match(\n    account: &dyn Account,\n    reservations: &AHashMap<Currency, Money>,\n) -> bool {\n    for reservation in reservations.values() {\n        let Some(balance) = account.balance(Some(reservation.currency)) else {\n            continue;\n        };\n\n        if balance.currency.precision != reservation.currency.precision {\n            log::error!(\n                \"Cannot update {} reservation: precision {} differed from balance precision {}\",\n                reservation.currency,\n                reservation.currency.precision,","sourceCodeStart":1425,"sourceCodeEnd":1461,"githubUrl":"https://github.com/nautechsystems/nautilus_trader/blob/18893faf8b356be3320add8de2f861b0b647cf06/crates/portfolio/src/manager.rs#L1425-L1461","documentation":"wallet_money_from_quantity converts a Quantity's raw integer value into a Money amount in the account currency. After adjusting the raw value for the currency's precision it performs a fixed-width i128 range check (check_fixed_raw_i128) and then attempts to fit the value into Money's internal raw integer representation (MoneyRaw). If the value is too large to fit that narrower integer type, the TryInto conversion fails and this error is thrown.","triggerScenarios":"Calling update_balance_locked_wallet (directly or via balance updates) with a quantity whose raw value, after precision adjustment to the currency's precision, exceeds the maximum (or minimum) value representable by MoneyRaw — e.g. very large account balances in low-precision currencies like USD (2 dp).","commonSituations":"Trading venues or test environments reporting enormous balances; manually seeded account state with unadjusted raw quantities; currencies with few decimals where a large quantity multiplied by precision overflows; bugs in upstream balance parsing that pass unscaled values.","solutions":["Verify the quantity/balance value from the venue is scaled correctly for the currency precision before it reaches the wallet","Check currency.precision: low-precision currencies (fewer decimals) allow less headroom before overflow — use a higher-precision currency or cap the value","Confirm the build's MoneyRaw width (fixed i128 bounds via check_fixed_raw_i128) matches the magnitudes your strategy trades","Log the failing quantity, currency, and precision at the call site to confirm which side (quantity vs precision scaling) produces the out-of-range value"],"exampleFix":"// before: passing a raw quantity already scaled for the venue, re-scaled again\nlet money = wallet_money_from_quantity(&qty, &usd_currency)?;\n// after: ensure the quantity is in units, not scaled raw, before conversion\nlet qty = Quantity::new(balance_total.as_f64(), usd_currency.precision);\nlet money = wallet_money_from_quantity(&qty, &usd_currency)?;","handlingStrategy":"validation","validationCode":"fn quantity_fits_money_raw(qty: &Quantity, currency: &Currency) -> bool {\n    let raw = qty.raw.as_i128();\n    // 10^precision scaling must stay within i128 bounds used by MoneyRaw\n    let scaled = raw.checked_mul(10i128.checked_pow(currency.precision as u32).unwrap_or(i128::MAX));\n    match scaled {\n        Some(v) => v >= i128::MIN / 1_000_000 && v <= i128::MAX / 1_000_000, // conservative bound\n        None => false,\n    }\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Validate venue-reported balances against a sane maximum before applying them to the wallet","Prefer currencies/precisions that give headroom for your position sizes","Scale quantities correctly once at the adapter boundary, not repeatedly downstream"],"tags":["overflow","money","quantity","portfolio"],"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-14T00:17:10.932Z"}