nautechsystems/nautilus_trader · error
Cannot update {currency} reservation: precision {} differed
Error message
Cannot update {currency} reservation: precision {} differed from balance precision {} What it means
A balance reservation for a currency must have the same decimal precision as the account's existing balance in that currency; a differing precision would corrupt the balance arithmetic. The guard rejects the reservation update when `locked.currency.precision` differs from the current balance currency's precision.
Source
Thrown at crates/model/src/accounts/base.rs:442
/// or the reservations cannot produce a valid balance. Balances and reservations are left
/// unchanged when an error is returned.
pub(crate) fn update_balance_locked(
balances: &mut IndexMap<Currency, AccountBalance>,
balances_locked: &mut AHashMap<(InstrumentId, Currency), Money>,
instrument_id: InstrumentId,
locked: Money,
) -> anyhow::Result<()> {
anyhow::ensure!(locked.raw >= 0, "locked balance was negative: {locked}");
let currency = locked.currency;
let key = (instrument_id, currency);
let Some(current_balance) = balances.get(¤cy).copied() else {
balances_locked.insert(key, locked);
return Ok(());
};
anyhow::ensure!(
current_balance.currency.precision == currency.precision,
"Cannot update {currency} reservation: precision {} differed from balance precision {}",
currency.precision,
current_balance.currency.precision
);
let previous = balances_locked.insert(key, locked);
match balance_from_locks(current_balance, balances_locked) {
Ok(balance) => {
balances.insert(currency, balance);
Ok(())
}
Err(e) => {
// Restore the prior reservation so a rejected update leaves nothing behind
match previous {
Some(previous) => balances_locked.insert(key, previous),
None => balances_locked.remove(&key),View on GitHub (pinned to 18893faf8b)
Solutions
- Construct the locked Money using the same Currency instance/precision as the account balance (use Currency.from_str or the canonical currency)
- Normalize adapter-reported precision to the account's precision before reserving
- Check the account's balance snapshot to confirm the precision the account expects
Defensive patterns
Strategy: validation
Validate before calling
if locked.currency.precision != balances[locked.currency].currency.precision:
locked = Money(locked.as_decimal(), balances[locked.currency].currency) Try / catch
try:
update_balance_locked(balances, locks, instrument_id, locked)
except Exception as e:
log.warning(f"reservation rejected: {e}") Prevention
- Always build Money from the canonical Currency instance
- Normalize adapter precision to account precision on ingest
- Avoid ad-hoc Currency constructions with custom precision
When it happens
Trigger: Calling update_balance_locked with a Money whose currency carries a different precision than the precision of the account's existing balance for that currency (e.g. BTC with 8 vs 6 digits, or USD 2 vs 0).
Common situations: Adapters reporting balances/reservations with different decimal precision than the configured account currency, currency objects constructed ad hoc with the wrong precision, or mixing custom Currency instances with the canonical ones.
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
- Instrument not found in cache: {symbol}
- {FAILED}: {e}
- AX dated contract {} has different quote and settlement curr
- AX {field} scale must not exceed 26 for exact percent conver
- invalid {field}='{raw}' at precision {precision}: {e}
AI-assisted analysis of nautechsystems/nautilus_trader@18893faf8b (2026-09-08).
Data as JSON: /api/errors/6ee37648012c132d.
Report an issue: GitHub.