nautechsystems/nautilus_trader · error
Cannot apply betting account state: balance would be negativ
Error message
Cannot apply betting account state: balance would be negative {} {} ({}) What it means
BettingAccountState::apply rejects an AccountState event whose balance total is negative, because a betting account cannot hold a negative balance. The library bails with anyhow::Error naming the total, currency, and account id. It guards against corrupt or miscomputed account event data.
Source
Thrown at crates/model/src/accounts/betting.rs:177
}
impl Account for BettingAccount {
impl_account_base_members!();
fn is_cash_account(&self) -> bool {
true
}
fn is_margin_account(&self) -> bool {
false
}
fn apply(&mut self, event: AccountState) -> anyhow::Result<()> {
self.check_event_account_id(&event)?;
for balance in &event.balances {
if balance.total.raw < 0 {
anyhow::bail!(
"Cannot apply betting account state: balance would be negative {} {} ({})",
balance.total.as_decimal(),
balance.currency.code,
self.id
);
}
}
if event.is_reported {
self.balances_locked.clear();
}
self.base_apply(event);
Ok(())
}
fn calculate_balance_locked(
&self,View on GitHub (pinned to 18893faf8b)
Solutions
- Inspect the AccountState event balances and correct the negative total values at the source before applying
- If the negative balance is legitimate, use a cash/margin account with allow_borrowing instead of a betting account
- Verify upstream balance computation (deposits/withdrawals/adjustments) for sign errors
Example fix
// before: event with negative total let mut state = AccountState::new(...); state.balances = vec![AccountBalance::new(Money::from(-100.0, AUD), ...)]; account.apply(state)?; // bails // after: ensure non-negative total assert!(total.as_decimal() >= Decimal::ZERO); account.apply(state)?;
Defensive patterns
Strategy: validation
Validate before calling
if event.balances.iter().any(|b| b.total.raw < 0) { return Err(anyhow!("event has negative balance")); }
account.apply(event)?; Type guard
fn has_non_negative_balances(event: &AccountState) -> bool {
event.balances.iter().all(|b| b.total.raw >= 0)
} Try / catch
match account.apply(event) {
Err(e) if e.to_string().contains("balance would be negative") => { /* fix event data */ }
other => other?,
} Prevention
- Check balance signs when building AccountState events
- Never reuse margin/cash event data for betting accounts
- Add unit tests asserting non-negative totals for generated events
When it happens
Trigger: Calling apply() (or py_apply / betting_account_from_account_events) with an AccountState whose event.balances contains any balance with total.raw < 0.
Common situations: Feeding incorrectly signed balance data from a backtest fill model, converting balances from a broker export with wrong signs, or constructing AccountState events by hand with negative totals.
Understand the failure class
Background: "Invalid state transition" errors: "status must be X, actually Y", "already rejected/charging/uninstalled", "cannot ... while running" — what they mean when a library rejects your call — this error's family across 31 libraries.
Related errors
- Cash account balance would become negative: {} {} (borrowing
- Cannot apply account state: balance would be negative {} {}
- {e}
- {FAILED}: {e}
- {FAILED}: {e}
AI-assisted analysis of nautechsystems/nautilus_trader@18893faf8b (2026-09-08).
Data as JSON: /api/errors/e0dc170d870a2315.
Report an issue: GitHub.