nautechsystems/nautilus_trader · error
Wallet balance snapshot has no native currency
Error message
Wallet balance snapshot has no native currency
What it means
account_balances builds a Vec<AccountBalance> from a wallet snapshot, requiring a native currency balance as the first entry. This error means the snapshot's native_currency field is None — the wallet snapshot is incomplete and cannot be converted into account balances. The library throws it because an account balance report without the chain's native asset would be misleading.
Source
Thrown at crates/model/src/defi/wallet.rs:184
/// # Errors
///
/// Returns an error if the snapshot is incomplete, contains duplicate currencies, or a token
/// amount cannot be represented as money.
pub fn as_account_balances(&self) -> anyhow::Result<Vec<AccountBalance>> {
let mut token_balances = self.token_balances.iter().collect::<Vec<_>>();
token_balances.sort_unstable_by_key(|balance| balance.token.address);
self.account_balances(token_balances)
}
fn account_balances<'a>(
&'a self,
token_balances: impl IntoIterator<Item = &'a TokenBalance>,
) -> anyhow::Result<Vec<AccountBalance>> {
self.validate_token_addresses()?;
let native_currency = self
.native_currency
.ok_or_else(|| anyhow::anyhow!("Wallet balance snapshot has no native currency"))?;
let mut currencies = HashSet::new();
currencies.insert(native_currency.currency);
let mut balances = Vec::with_capacity(self.token_balances.len() + 1);
balances.push(AccountBalance::new_checked(
native_currency,
Money::zero(native_currency.currency),
native_currency,
)?);
for token_balance in token_balances {
let total = token_balance.as_money()?;
if !currencies.insert(total.currency) {
anyhow::bail!(
"Wallet balance snapshot contains duplicate currency {}",
total.currency
);
}View on GitHub (pinned to 18893faf8b)
Solutions
- Call set_native_currency_balance() (or replace_balances()) before as_account_balances().
- Guard with is_token_universe_initialized-style checks / check native currency presence before converting.
- Re-request the full balance snapshot from the adapter instead of converting a partial one.
- Wait for the wallet's initial snapshot event before consuming account balances.
Example fix
// before
let balances = snapshot.as_account_balances()?;
// after
if !snapshot.is_token_universe_initialized() { /* or track native presence */ }
let balances = match snapshot.as_account_balances() {
Ok(b) => b,
Err(e) if e.to_string().contains("no native currency") => {
tracing::warn!("wallet snapshot not yet populated");
return Ok(vec![]);
}
Err(e) => return Err(e),
}; Defensive patterns
Strategy: validation
Validate before calling
fn snapshot_has_native(snapshot: &WalletBalanceSnapshot) -> bool {
snapshot.as_account_balances().is_ok() // or expose/track native_currency presence at construction
} Try / catch
match snapshot.as_account_balances() {
Ok(balances) => balances,
Err(e) if e.to_string().contains("no native currency") => {
tracing::debug!("wallet snapshot incomplete; skipping balance report");
Vec::new()
}
Err(e) => return Err(e),
} Prevention
- Always call set_native_currency_balance() or replace_balances() before reading balances
- Only convert snapshots after the adapter's initial balance event
- Track whether the snapshot was populated to avoid converting empty state
When it happens
Trigger: Calling as_account_balances() on a WalletBalanceSnapshot created via the empty constructor (or any snapshot) before set_native_currency_balance()/replace_balances() has been called to populate the native balance.
Common situations: Querying balances before the first balance snapshot arrives from the adapter; constructing the snapshot manually and forgetting the native currency; a failed native balance fetch leaving the field unset while token balances were updated.
Understand the failure class
Background: "must not be empty", "cannot be empty" — required-field validation errors across open-source libraries — this error's family across 41 libraries.
Related errors
- Wallet balance snapshot contains duplicate currency {}
- Native currency not specified for chain {}
- Must have the `chain` field set
- `InstrumentId` not applicable to `Block`
- Invalid factory address for DEX {name} on chain {chain} for
AI-assisted analysis of nautechsystems/nautilus_trader@18893faf8b (2026-09-08).
Data as JSON: /api/errors/5911cbba2b7b65ad.
Report an issue: GitHub.