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

  1. Inspect the account's collaterals on Derive and correct the negative/invalid balance at the venue
  2. Upgrade/patch parsing to skip or clamp invalid collateral entries defensively
  3. 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

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


AI-assisted analysis of nautechsystems/nautilus_trader@18893faf8b (2026-09-08). Data as JSON: /api/errors/cc53172cfa5dab04. Report an issue: GitHub.