nautechsystems/nautilus_trader · error
failed to build collateral balance for {} (total={}): {e}
Error message
failed to build collateral balance for {} (total={}): {e} What it means
When converting a Derive subaccount collateral entry into a Nautilus AccountBalance, the total amount fails to produce a valid balance (AccountBalance::from_total_and_locked with locked=ZERO). The error wraps the currency name and raw total amount so the offending collateral can be identified.
Source
Thrown at crates/adapters/derive/src/http/parse.rs:345
/// subaccount's `initial_margin`/`maintenance_margin` are signed net health
/// values, not requirements, so they travel in the returned [`Params`] as
/// `net_initial_margin`/`net_maintenance_margin` alongside the requirement
/// split and the liquidation flag.
///
/// # Errors
///
/// Returns an error when a decimal field cannot be represented at the
/// currency precision used by [`Money`].
pub fn parse_derive_subaccount_to_balances(
subaccount: &DeriveSubaccount,
) -> anyhow::Result<(Vec<AccountBalance>, Vec<MarginBalance>, Params)> {
let mut balances = Vec::with_capacity(subaccount.collaterals.len());
for collateral in &subaccount.collaterals {
let currency = Currency::get_or_create_crypto(collateral.asset_name);
let balance =
AccountBalance::from_total_and_locked(collateral.amount, Decimal::ZERO, currency)
.map_err(|e| {
anyhow::anyhow!(
"failed to build collateral balance for {} (total={}): {e}",
collateral.asset_name,
collateral.amount,
)
})?;
balances.push(balance);
}
let currency = Currency::get_or_create_crypto(subaccount.currency);
let initial_dec = subaccount.positions_initial_margin + subaccount.open_orders_margin;
let maintenance_dec = subaccount.positions_maintenance_margin;
let initial = Money::from_decimal(initial_dec, currency).with_context(|| {
format!(
"initial margin requirement {initial_dec} cannot be represented at {currency} precision",
)
})?;
let maintenance =
Money::from_decimal(maintenance_dec, currency).with_context(|| {View on GitHub (pinned to 18893faf8b)
Solutions
- Inspect the account's collaterals on Derive and correct the negative/invalid balance at the venue
- Upgrade/patch parsing to skip or clamp invalid collateral entries defensively
- Verify the Derive API response shape hasn't changed and report discrepancies
Example fix
// before
let balance = AccountBalance::from_total_and_locked(collateral.amount, Decimal::ZERO, currency)?;
// after (defensive skip)
let balance = match AccountBalance::from_total_and_locked(collateral.amount, Decimal::ZERO, currency) {
Ok(b) => Some(b),
Err(e) => { tracing::warn!("skipping invalid collateral {}: {e}", collateral.asset_name); None }
}; Defensive patterns
Strategy: try-catch
Validate before calling
fn collateral_is_valid(c: &DeriveCollateral) -> bool { c.amount >= Decimal::ZERO } Try / catch
match parse_derive_subaccount_to_balances(&subaccount) { Ok(b) => b, Err(e) => { warn!("bad collateral parse: {e}"); refresh_account_state()? } } Prevention
- Validate collateral amounts are non-negative before parsing
- Log the raw API payload on parse failure for diagnostics
- Monitor Derive account state for negative balances at the venue
When it happens
Trigger: parse_derive_subaccount_to_balances encounters a collateral whose amount cannot build a valid AccountBalance — typically a negative or otherwise invalid Decimal total returned by the Derive API.
Common situations: Derive API returning negative or corrupted collateral amounts for an account; a currency/asset whose precision setup makes the amount invalid; unexpected API responses after venue-side changes.
Understand the failure class
Background: "Must be a positive integer", "Invalid value", "Unsupported": the invalid-argument-value error family, when a library rejects the value you pass — this error's family across 35 libraries.
Related errors
- Unknown position currency '{pos_ccy}' for instrument {instru
- Invalid timeframe for `BarSpecification`, was {timeframe}
- invalid Derive `expired` filter: {e}
- Invalid scientific notation exponent '{exponent}': must be a
- {FAILED}: {e}
AI-assisted analysis of nautechsystems/nautilus_trader@18893faf8b (2026-09-08).
Data as JSON: /api/errors/cc53172cfa5dab04.
Report an issue: GitHub.