{"record":{"id":"cc53172cfa5dab04","repo":"nautechsystems/nautilus_trader","slug":"failed-to-build-collateral-balance-for-total","errorCode":null,"errorMessage":"failed to build collateral balance for {} (total={}): {e}","messagePattern":"failed to build collateral balance for (.+?) \\(total=(.+?)\\): (.+?)","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"crates/adapters/derive/src/http/parse.rs","lineNumber":345,"sourceCode":"/// subaccount's `initial_margin`/`maintenance_margin` are signed net health\n/// values, not requirements, so they travel in the returned [`Params`] as\n/// `net_initial_margin`/`net_maintenance_margin` alongside the requirement\n/// split and the liquidation flag.\n///\n/// # Errors\n///\n/// Returns an error when a decimal field cannot be represented at the\n/// currency precision used by [`Money`].\npub fn parse_derive_subaccount_to_balances(\n    subaccount: &DeriveSubaccount,\n) -> anyhow::Result<(Vec<AccountBalance>, Vec<MarginBalance>, Params)> {\n    let mut balances = Vec::with_capacity(subaccount.collaterals.len());\n    for collateral in &subaccount.collaterals {\n        let currency = Currency::get_or_create_crypto(collateral.asset_name);\n        let balance =\n            AccountBalance::from_total_and_locked(collateral.amount, Decimal::ZERO, currency)\n                .map_err(|e| {\n                    anyhow::anyhow!(\n                        \"failed to build collateral balance for {} (total={}): {e}\",\n                        collateral.asset_name,\n                        collateral.amount,\n                    )\n                })?;\n        balances.push(balance);\n    }\n\n    let currency = Currency::get_or_create_crypto(subaccount.currency);\n    let initial_dec = subaccount.positions_initial_margin + subaccount.open_orders_margin;\n    let maintenance_dec = subaccount.positions_maintenance_margin;\n    let initial = Money::from_decimal(initial_dec, currency).with_context(|| {\n        format!(\n            \"initial margin requirement {initial_dec} cannot be represented at {currency} precision\",\n        )\n    })?;\n    let maintenance =\n        Money::from_decimal(maintenance_dec, currency).with_context(|| {","sourceCodeStart":327,"sourceCodeEnd":363,"githubUrl":"https://github.com/nautechsystems/nautilus_trader/blob/18893faf8b356be3320add8de2f861b0b647cf06/crates/adapters/derive/src/http/parse.rs#L327-L363","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","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"],"exampleFix":"// before\nlet balance = AccountBalance::from_total_and_locked(collateral.amount, Decimal::ZERO, currency)?;\n// after (defensive skip)\nlet balance = match AccountBalance::from_total_and_locked(collateral.amount, Decimal::ZERO, currency) {\n    Ok(b) => Some(b),\n    Err(e) => { tracing::warn!(\"skipping invalid collateral {}: {e}\", collateral.asset_name); None }\n};","handlingStrategy":"try-catch","validationCode":"fn collateral_is_valid(c: &DeriveCollateral) -> bool { c.amount >= Decimal::ZERO }","typeGuard":null,"tryCatchPattern":"match parse_derive_subaccount_to_balances(&subaccount) { Ok(b) => b, Err(e) => { warn!(\"bad collateral parse: {e}\"); refresh_account_state()? } }","preventionTips":["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"],"tags":["rust","adapter","parsing","balances"],"backgroundTag":"invalid-argument-value","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"}