{"record":{"id":"eb3c74d5326201db","repo":"nautechsystems/nautilus_trader","slug":"cash-account-balance-would-become-negative","errorCode":null,"errorMessage":"Cash account balance would become negative: {} {} (borrowing not allowed for {})","messagePattern":"Cash account balance would become negative: (.+?) (.+?) \\(borrowing not allowed for (.+?)\\)","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"crates/model/src/accounts/cash.rs","lineNumber":136,"sourceCode":"        base::clear_balance_locked(\n            &mut self.base.balances,\n            &mut self.balances_locked,\n            instrument_id,\n        );\n    }\n\n    /// Updates the account balances, enforcing borrowing constraints.\n    ///\n    /// # Errors\n    ///\n    /// Returns an error if `allow_borrowing` is false and any balance has a negative total.\n    ///\n    /// TODO: Force stop backtest engine on error (like Python's `set_backtest_force_stop`)\n    pub fn update_balances(&mut self, balances: &[AccountBalance]) -> anyhow::Result<()> {\n        if !self.allow_borrowing {\n            for balance in balances {\n                if balance.total.raw < 0 {\n                    anyhow::bail!(\n                        \"Cash account balance would become negative: {} {} (borrowing not allowed for {})\",\n                        balance.total.as_decimal(),\n                        balance.currency.code,\n                        self.id\n                    );\n                }\n            }\n        }\n        self.base.update_balances(balances);\n        Ok(())\n    }\n\n    #[must_use]\n    pub fn is_cash_account(&self) -> bool {\n        self.account_type == AccountType::Cash\n    }\n\n    #[must_use]","sourceCodeStart":118,"sourceCodeEnd":154,"githubUrl":"https://github.com/nautechsystems/nautilus_trader/blob/18893faf8b356be3320add8de2f861b0b647cf06/crates/model/src/accounts/cash.rs#L118-L154","documentation":"CashAccount::update_balances rejects negative balance totals when the account was created with allow_borrowing=false, since a cash account without borrowing cannot go below zero. The error reports the total, currency, and account id.","triggerScenarios":"Calling update_balances() on a CashAccount with allow_borrowing=false and any AccountBalance in the slice whose total.raw < 0.","commonSituations":"Backtest engines applying withdrawal/fee events that overdraw a non-borrowing cash account; configuring an account without borrowing then routing margin-like flows through it.","solutions":["Enable borrowing at account construction if negative balances are expected","Correct the balance data so totals stay non-negative","Route flows requiring negative balances to a margin account instead"],"exampleFix":"// before\nlet mut acct = CashAccount::new(..., false); // allow_borrowing=false\nacct.update_balances(&balances_with_negative_total)?; // bails\n// after\nlet mut acct = CashAccount::new(..., true); // allow_borrowing=true\nacct.update_balances(&balances_with_negative_total)?;","handlingStrategy":"validation","validationCode":"if !acct.allows_borrowing() && balances.iter().any(|b| b.total.raw < 0) { /* reject or enable borrowing */ }\nacct.update_balances(balances)?;","typeGuard":"fn balances_non_negative(bs: &[AccountBalance]) -> bool {\n    bs.iter().all(|b| b.total.raw >= 0)\n}","tryCatchPattern":"match acct.update_balances(balances) {\n    Err(e) if e.to_string().contains(\"would become negative\") => { /* enable borrowing or clamp */ }\n    other => other?,\n}","preventionTips":["Match allow_borrowing to the account's realistic cash flows","Clamp or reject overdrawing withdrawals upstream","Log near-zero balances to detect borrowing needs early"],"tags":["rust","accounts","cash","balance","borrowing"],"backgroundTag":"invalid-state-transition","analyzedSha":"18893faf8b356be3320add8de2f861b0b647cf06","analyzedAt":"2026-09-08T20:49:34.690Z","contentChangedAt":"2026-09-08T20:49:34.690Z","schemaVersion":2},"datasetVersion":"2026-09-14T00:17:10.932Z"}