nautechsystems/nautilus_trader · error
wallet has no observed balance for {source_currency}
Error message
wallet has no observed balance for {source_currency} What it means
calculate_balance_locked computes the locked balance for a prospective order in the source currency, but requires an already-observed balance for that currency to validate sufficient funds. If the wallet has no observed balance entry for source_currency, this error is raised because free/locked amounts cannot be determined.
Source
Thrown at crates/model/src/accounts/wallet.rs:644
let base_currency = instrument
.base_currency()
.unwrap_or(instrument.quote_currency());
let source_currency = if instrument.is_inverse() && !use_quote_for_inverse.unwrap_or(false)
{
base_currency
} else {
match side {
OrderSide::Buy => instrument.quote_currency(),
OrderSide::Sell => base_currency,
}
};
let current_balance = self
.base
.balances
.get(&source_currency)
.copied()
.ok_or_else(|| {
anyhow::anyhow!("wallet has no observed balance for {source_currency}")
})?;
Self::validate_observed_balance(current_balance)?;
if side == OrderSide::Sell {
return Self::money_from_quantity(quantity, current_balance.currency)
.map_err(Into::into);
}
Self::validate_quantity(quantity)?;
Self::validate_price(price)?;
if !instrument.is_inverse() && !instrument.is_quanto() {
return Self::calculate_notional_exact(
instrument,
quantity,
price,
current_balance.currency,
)View on GitHub (pinned to 18893faf8b)
Solutions
- Apply the initial account balance state before querying calculate_balance_locked
- Check observed balances for the currency before the call and return a clear 'not ready' state
- Verify the adapter emits balances for every currency used in orders
Example fix
// before
let locked = wallet.calculate_balance_locked(¤cy, side, qty, &instrument).unwrap();
// after
let locked = wallet
.calculate_balance_locked(¤cy, side, qty, &instrument)
.ok() // or map to "balance not yet observed"
.unwrap_or_default(); Defensive patterns
Strategy: validation
Validate before calling
if wallet.balances().get(&source_currency).is_none() {
bail!("source currency {} not yet observed", source_currency);
} Type guard
fn has_observed_balance(wallet: &AccountWallet, c: &Currency) -> bool {
wallet.balances().contains_key(c)
} Try / catch
match wallet.calculate_balance_locked(&cur, side, qty, &inst) {
Ok(v) => v,
Err(e) if e.to_string().contains("no observed balance") => default_locked,
Err(e) => return Err(e),
} Prevention
- Wait for the account state (balances) event before computing locked balances
- Verify adapter reports all currencies used in orders
- Cache a 'balances ready' flag per account
When it happens
Trigger: Calling calculate_balance_locked (or its Python wrapper py_calculate_balance_locked) with a source_currency that has no entry in the wallet's observed balances — typically before any balance event was applied for that currency.
Common situations: Querying margin/locked balance at startup before the exchange adapter delivers balance snapshots; asking about a currency the account never trades or reports; side=Buy paths needing the base currency which was never observed.
Understand the failure class
Background: 'Could not be found', 'does not exist', 'not found in database': the resource-not-found family when an ID, slug, key, or URI lookup comes back empty — this error's family across 20 libraries.
Related errors
- wallet has no observed balance for {}
- cannot rebuild Wallet reservations for account {account_id}
- default client already registered
- Already running
- Cannot set cache database while node is running, set it befo
AI-assisted analysis of nautechsystems/nautilus_trader@18893faf8b (2026-09-08).
Data as JSON: /api/errors/306c2ee6b131adf1.
Report an issue: GitHub.