{"record":{"id":"306c2ee6b131adf1","repo":"nautechsystems/nautilus_trader","slug":"wallet-has-no-observed-balance-for-source-currenc","errorCode":null,"errorMessage":"wallet has no observed balance for {source_currency}","messagePattern":"wallet has no observed balance for (.+?)","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"crates/model/src/accounts/wallet.rs","lineNumber":644,"sourceCode":"        let base_currency = instrument\n            .base_currency()\n            .unwrap_or(instrument.quote_currency());\n        let source_currency = if instrument.is_inverse() && !use_quote_for_inverse.unwrap_or(false)\n        {\n            base_currency\n        } else {\n            match side {\n                OrderSide::Buy => instrument.quote_currency(),\n                OrderSide::Sell => base_currency,\n            }\n        };\n        let current_balance = self\n            .base\n            .balances\n            .get(&source_currency)\n            .copied()\n            .ok_or_else(|| {\n                anyhow::anyhow!(\"wallet has no observed balance for {source_currency}\")\n            })?;\n        Self::validate_observed_balance(current_balance)?;\n\n        if side == OrderSide::Sell {\n            return Self::money_from_quantity(quantity, current_balance.currency)\n                .map_err(Into::into);\n        }\n\n        Self::validate_quantity(quantity)?;\n        Self::validate_price(price)?;\n\n        if !instrument.is_inverse() && !instrument.is_quanto() {\n            return Self::calculate_notional_exact(\n                instrument,\n                quantity,\n                price,\n                current_balance.currency,\n            )","sourceCodeStart":626,"sourceCodeEnd":662,"githubUrl":"https://github.com/nautechsystems/nautilus_trader/blob/18893faf8b356be3320add8de2f861b0b647cf06/crates/model/src/accounts/wallet.rs#L626-L662","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","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"],"exampleFix":"// before\nlet locked = wallet.calculate_balance_locked(&currency, side, qty, &instrument).unwrap();\n// after\nlet locked = wallet\n    .calculate_balance_locked(&currency, side, qty, &instrument)\n    .ok()  // or map to \"balance not yet observed\"\n    .unwrap_or_default();","handlingStrategy":"validation","validationCode":"if wallet.balances().get(&source_currency).is_none() {\n    bail!(\"source currency {} not yet observed\", source_currency);\n}","typeGuard":"fn has_observed_balance(wallet: &AccountWallet, c: &Currency) -> bool {\n    wallet.balances().contains_key(c)\n}","tryCatchPattern":"match wallet.calculate_balance_locked(&cur, side, qty, &inst) {\n    Ok(v) => v,\n    Err(e) if e.to_string().contains(\"no observed balance\") => default_locked,\n    Err(e) => return Err(e),\n}","preventionTips":["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"],"tags":["rust","wallet","balance","state"],"backgroundTag":"resource-not-found","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"}