nautechsystems/nautilus_trader · error · anyhow::Error

Failed to fetch CFM positions: {e}

Error message

Failed to fetch CFM positions: {e}

What it means

This error wraps any failure from the Coinbase `get_cfm_positions` HTTP call while building a list of `PositionStatusReport`s for futures positions. It means the CFM positions endpoint request failed at the HTTP/API level — auth, entitlement, network, or API error. It is thrown because position reconciliation for CFM cannot proceed without the positions payload.

Source

Thrown at crates/adapters/coinbase/src/http/client.rs:1485

        let ts_event = self.ts_now();
        parse_cfm_account_state(&summary, account_id, true, ts_event, ts_event)
    }

    /// Fetches all CFM futures positions and returns Nautilus position reports.
    ///
    /// # Errors
    ///
    /// Returns an error when the HTTP request fails or a position cannot be
    /// parsed.
    pub async fn request_position_status_reports(
        &self,
        account_id: AccountId,
    ) -> anyhow::Result<Vec<PositionStatusReport>> {
        let response = self
            .inner
            .get_cfm_positions()
            .await
            .map_err(|e| anyhow::anyhow!("Failed to fetch CFM positions: {e}"))?;

        let ts_init = self.ts_now();
        let mut reports = Vec::with_capacity(response.positions.len());

        for position in &response.positions {
            let instrument = match self.get_or_fetch_instrument(position.product_id).await {
                Ok(inst) => inst,
                Err(e) => {
                    log::debug!("Skipping CFM position {}: {e}", position.product_id);
                    continue;
                }
            };

            match parse_cfm_position_status_report(position, &instrument, account_id, ts_init) {
                Ok(report) => reports.push(report),
                Err(e) => log::warn!("Failed to parse CFM position {}: {e}", position.product_id),
            }
        }

View on GitHub (pinned to 18893faf8b)

Solutions

  1. Check the wrapped inner error for the specific cause (status code, Coinbase message).
  2. Verify the account has Coinbase Financial Markets access and the keys include futures scopes.
  3. Retry transient errors with exponential backoff.
  4. Disable/skip CFM position reconciliation if the account is not futures-enabled.
  5. Confirm the endpoint is reachable from your region.

Example fix

// before: hard failure aborts all reconciliation
let reports = client.request_cfm_position_status_reports(account_id).await?;
// after: tolerate CFM unavailability
let reports = match client.request_cfm_position_status_reports(account_id).await {
    Ok(r) => r,
    Err(e) => {
        tracing::warn!("CFM positions unavailable: {e}");
        Vec::new()
    }
};
Defensive patterns

Strategy: try-catch

Validate before calling

if !account_config.cfm_enabled {
    return Ok(Vec::new()); // skip CFM position reconciliation entirely
}

Try / catch

match client.request_cfm_position_status_reports(account_id).await {
    Ok(reports) => apply(reports),
    Err(e) => tracing::warn!("CFM position reports failed, skipping: {e}"),
}

Prevention

When it happens

Trigger: Calling the CFM positions report method at client.rs:1485 when `get_cfm_positions` fails: account without futures entitlement, keys lacking CFM scope, 401/403, rate limit, network drop.

Common situations: Futures reconciliation configured for a spot-only account; API keys regenerated without CFM scope; regional restrictions on Coinbase futures; transient outages during periodic position polling.

Understand the failure class

Background: "API error: {status}" and "HTTP 401/403/404/429/5xx" errors: non-2xx HTTP responses explained — this error's family across 27 libraries.

Related errors


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