nautechsystems/nautilus_trader · error · anyhow::Error

No margin data returned from BitMEX

Error message

No margin data returned from BitMEX

What it means

When building an account state, request_account_statre collects margin/balance data from the BitMEX /user/margin response; if no margin rows were converted into balances, it bails because an account state cannot be constructed without any balance data.

Source

Thrown at crates/adapters/bitmex/src/http/client.rs:1608

                Decimal::from(margin_msg.maint_margin.unwrap_or(0).max(0)) / divisor;

            if !initial_dec.is_zero() || !maintenance_dec.is_zero() {
                let currency = balance.total.currency;
                // BitMEX reports cross-margin aggregates per collateral currency.
                margins_vec.push(MarginBalance::new(
                    Money::from_decimal(initial_dec, currency)
                        .unwrap_or_else(|_| Money::zero(currency)),
                    Money::from_decimal(maintenance_dec, currency)
                        .unwrap_or_else(|_| Money::zero(currency)),
                    None,
                ));
            }

            balances.push(balance);
        }

        if balances.is_empty() {
            anyhow::bail!("No margin data returned from BitMEX");
        }

        let account_type = AccountType::Margin;
        let is_reported = true;
        let event_id = UUID4::new();

        // Use server timestamp if available, otherwise fall back to local time
        let ts_event = latest_timestamp.map_or(ts_init, |ts| {
            UnixNanos::from(u64::try_from(ts.as_nanosecond()).unwrap_or_default())
        });

        Ok(AccountState::new(
            account_id,
            account_type,
            balances,
            margins_vec,
            is_reported,
            event_id,

View on GitHub (pinned to 18893faf8b)

Solutions

  1. Verify the account has funds/margin for the requested currency on BitMEX
  2. Check the currency/instrument ID used in the request
  3. Inspect the raw HTTP response for empty /user/margin payloads and confirm API credentials and account status
Defensive patterns

Strategy: try-catch

Try / catch

match client.request_account_state(currency).await {
    Ok(state) => state,
    Err(e) if e.to_string().contains("No margin data") => {
        log::warn!("no margin data for {currency}; skipping account state");
        Default::default()
    }
    Err(e) => return Err(e),
}

Prevention

When it happens

Trigger: Calling request_account_state for a currency/account whose BitMEX margin response is empty or whose rows all fail conversion so `balances` ends up empty.

Common situations: Querying an account with no positions or wallet in the requested currency; wrong currency code; API returning an empty margin array for an unverified/unfunded account.

Understand the failure class

Background: EmptyResultError / "no results found": when an API or scraper succeeds but returns zero rows — this error's family across 9 libraries.

Related errors


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