{"record":{"id":"1ffb38ad792c5d91","repo":"nautechsystems/nautilus_trader","slug":"failed-to-fetch-cfm-positions-e","errorCode":null,"errorMessage":"Failed to fetch CFM positions: {e}","messagePattern":"Failed to fetch CFM positions: (.+?)","errorType":"exception","errorClass":"anyhow::Error","httpStatus":null,"severity":"error","filePath":"crates/adapters/coinbase/src/http/client.rs","lineNumber":1485,"sourceCode":"        let ts_event = self.ts_now();\n        parse_cfm_account_state(&summary, account_id, true, ts_event, ts_event)\n    }\n\n    /// Fetches all CFM futures positions and returns Nautilus position reports.\n    ///\n    /// # Errors\n    ///\n    /// Returns an error when the HTTP request fails or a position cannot be\n    /// parsed.\n    pub async fn request_position_status_reports(\n        &self,\n        account_id: AccountId,\n    ) -> anyhow::Result<Vec<PositionStatusReport>> {\n        let response = self\n            .inner\n            .get_cfm_positions()\n            .await\n            .map_err(|e| anyhow::anyhow!(\"Failed to fetch CFM positions: {e}\"))?;\n\n        let ts_init = self.ts_now();\n        let mut reports = Vec::with_capacity(response.positions.len());\n\n        for position in &response.positions {\n            let instrument = match self.get_or_fetch_instrument(position.product_id).await {\n                Ok(inst) => inst,\n                Err(e) => {\n                    log::debug!(\"Skipping CFM position {}: {e}\", position.product_id);\n                    continue;\n                }\n            };\n\n            match parse_cfm_position_status_report(position, &instrument, account_id, ts_init) {\n                Ok(report) => reports.push(report),\n                Err(e) => log::warn!(\"Failed to parse CFM position {}: {e}\", position.product_id),\n            }\n        }","sourceCodeStart":1467,"sourceCodeEnd":1503,"githubUrl":"https://github.com/nautechsystems/nautilus_trader/blob/18893faf8b356be3320add8de2f861b0b647cf06/crates/adapters/coinbase/src/http/client.rs#L1467-L1503","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","solutions":["Check the wrapped inner error for the specific cause (status code, Coinbase message).","Verify the account has Coinbase Financial Markets access and the keys include futures scopes.","Retry transient errors with exponential backoff.","Disable/skip CFM position reconciliation if the account is not futures-enabled.","Confirm the endpoint is reachable from your region."],"exampleFix":"// before: hard failure aborts all reconciliation\nlet reports = client.request_cfm_position_status_reports(account_id).await?;\n// after: tolerate CFM unavailability\nlet reports = match client.request_cfm_position_status_reports(account_id).await {\n    Ok(r) => r,\n    Err(e) => {\n        tracing::warn!(\"CFM positions unavailable: {e}\");\n        Vec::new()\n    }\n};","handlingStrategy":"try-catch","validationCode":"if !account_config.cfm_enabled {\n    return Ok(Vec::new()); // skip CFM position reconciliation entirely\n}","typeGuard":null,"tryCatchPattern":"match client.request_cfm_position_status_reports(account_id).await {\n    Ok(reports) => apply(reports),\n    Err(e) => tracing::warn!(\"CFM position reports failed, skipping: {e}\"),\n}","preventionTips":["Gate CFM calls behind a futures-enabled account flag.","Ensure API keys carry CFM scopes after credential rotation.","Separate futures reconciliation failures from spot ones.","Backoff on 429s in position polling loops."],"tags":["network","http","coinbase","futures","cfm","positions"],"backgroundTag":"http-error-response","analyzedSha":"18893faf8b356be3320add8de2f861b0b647cf06","analyzedAt":"2026-09-08T20:49:34.690Z","contentChangedAt":"2026-09-08T20:49:34.690Z","schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}