{"record":{"id":"955c2e521d7e5e1c","repo":"nautechsystems/nautilus_trader","slug":"order-cancellation-failed-status","errorCode":null,"errorMessage":"Order cancellation failed: {status}","messagePattern":"Order cancellation failed: (.+?)","errorType":"http","errorClass":null,"httpStatus":null,"severity":"error","filePath":"crates/adapters/kraken/src/http/futures/client.rs","lineNumber":2326,"sourceCode":"        client_order_id: Option<ClientOrderId>,\n        venue_order_id: Option<VenueOrderId>,\n    ) -> anyhow::Result<()> {\n        let _ = self\n            .get_cached_instrument(&instrument_id.symbol.inner())\n            .ok_or_else(|| InstrumentLookupError::not_found(instrument_id))?;\n\n        let order_id = venue_order_id.as_ref().map(|id| id.to_string());\n        let cli_ord_id = client_order_id.as_ref().map(truncate_cl_ord_id);\n\n        if order_id.is_none() && cli_ord_id.is_none() {\n            anyhow::bail!(\"Either client_order_id or venue_order_id must be provided\");\n        }\n\n        let response = self.inner.cancel_order(order_id, cli_ord_id).await?;\n\n        if response.result != KrakenApiResult::Success {\n            let status = &response.cancel_status.status;\n            anyhow::bail!(\"Order cancellation failed: {status}\");\n        }\n\n        Ok(())\n    }\n\n    /// Cancels multiple orders on the Kraken Futures exchange.\n    ///\n    /// Automatically chunks requests into batches of 50 orders.\n    ///\n    /// # Parameters\n    /// - `venue_order_ids` - List of venue order IDs to cancel.\n    ///\n    /// # Returns\n    /// The total number of successfully cancelled orders.\n    pub async fn cancel_orders_batch(\n        &self,\n        venue_order_ids: Vec<VenueOrderId>,\n    ) -> anyhow::Result<usize> {","sourceCodeStart":2308,"sourceCodeEnd":2344,"githubUrl":"https://github.com/nautechsystems/nautilus_trader/blob/18893faf8b356be3320add8de2f861b0b647cf06/crates/adapters/kraken/src/http/futures/client.rs#L2308-L2344","documentation":"After sending a cancel request, Kraken Futures returned result != Success and the cancel_status.status string describes the failure (e.g. 'unknown order', 'already canceled'). The client surfaces that venue-side status verbatim as an anyhow error.","triggerScenarios":"Cancelling an order that was already filled or already cancelled; cancelling with a wrong/expired order id; venue rejection due to auth or rate issues reported in the cancel status; race where the order triggers between submit of cancel and venue processing.","commonSituations":"Aggressive strategies cancelling stale orders; retries after a network blip cancel twice; a strategy canceling an order that the exchange already matched; clock or reconciliation drift causing stale ids.","solutions":["Read the embedded status in the message: treat 'unknown order'/'notFound' and 'already canceled' as benign idempotent outcomes and handle them non-fatally.","Confirm the venue_order_id/client_order_id matches a live order via order status before cancelling.","Check exchange message status / websocket fills to see if the order completed before the cancel arrived.","Retry only on transient statuses; otherwise stop cancelling and reconcile position state."],"exampleFix":"// before: treat every failure as fatal\nclient.cancel_order(instrument_id, None, Some(cl_ord_id)).await?;\n\n// after: tolerate already-cancelled/unknown orders\nmatch client.cancel_order(instrument_id, None, Some(cl_ord_id)).await {\n    Ok(()) => {}\n    Err(e) if e.to_string().contains(\"already canceled\") || e.to_string().contains(\"unknown\") => {}\n    Err(e) => return Err(e),\n}","handlingStrategy":"try-catch","validationCode":"// confirm the order is still open via status before cancelling\nlet status = client.get_order_status(instrument_id, venue_order_id).await?;\nif status.is_terminal() { return Ok(()); }","typeGuard":"fn is_benign_cancel_failure(msg: &str) -> bool {\n    msg.contains(\"unknown order\") || msg.contains(\"already canceled\") || msg.contains(\"notFound\")\n}","tryCatchPattern":"match client.cancel_order(instrument_id, vid, cid).await {\n    Err(e) if is_benign_cancel_failure(&e.to_string()) => { /* idempotent: already done */ }\n    Err(e) => return Err(e),\n    Ok(_) => {}\n}","preventionTips":["Track terminal order states locally and skip cancels for filled/cancelled orders","Process websocket fill events promptly to keep order state current","Make cancel handling idempotent — retries are normal in trading loops"],"tags":["cancel-order","venue-rejection","kraken-futures","http"],"backgroundTag":"api-error-response","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"}