{"record":{"id":"5ad5eb6fdeeb693e","repo":"nautechsystems/nautilus_trader","slug":"failed-to-build-cancel-params-e","errorCode":null,"errorMessage":"Failed to build cancel params: {e}","messagePattern":"Failed to build cancel params: (.+?)","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"crates/adapters/kraken/src/http/spot/client.rs","lineNumber":2957,"sourceCode":"        let txid = venue_order_id.as_ref().map(|id| id.to_string());\n        let cl_ord_id = client_order_id.as_ref().map(truncate_cl_ord_id);\n\n        if txid.is_none() && cl_ord_id.is_none() {\n            anyhow::bail!(\"Either client_order_id or venue_order_id must be provided\");\n        }\n\n        // Prefer txid (venue identifier) since Kraken always knows it.\n        // cl_ord_id may not be known to Kraken for reconciled orders.\n        let mut builder = KrakenSpotCancelOrderParamsBuilder::default();\n\n        if let Some(ref id) = txid {\n            builder.txid(id.clone());\n        } else if let Some(ref id) = cl_ord_id {\n            builder.cl_ord_id(id.clone());\n        }\n        let params = builder\n            .build()\n            .map_err(|e| anyhow::anyhow!(\"Failed to build cancel params: {e}\"))?;\n\n        self.inner.cancel_order(&params).await?;\n\n        Ok(())\n    }\n\n    /// Cancels multiple orders on the Kraken Spot exchange (batched, max 50 per request).\n    pub async fn cancel_orders_batch(\n        &self,\n        venue_order_ids: Vec<VenueOrderId>,\n    ) -> anyhow::Result<i32> {\n        if venue_order_ids.is_empty() {\n            return Ok(0);\n        }\n\n        let mut total_cancelled = 0;\n\n        for chunk in venue_order_ids.chunks(BATCH_CANCEL_LIMIT) {","sourceCodeStart":2939,"sourceCodeEnd":2975,"githubUrl":"https://github.com/nautechsystems/nautilus_trader/blob/18893faf8b356be3320add8de2f861b0b647cf06/crates/adapters/kraken/src/http/spot/client.rs#L2939-L2975","documentation":"The cancel-order flow builds `CancelOrderParams` through a builder that validates the request. When `build()` rejects the field combination (e.g. missing transaction id / client order id), the adapter raises this anyhow error without sending the HTTP request. It signals the cancel parameters are structurally invalid, not that the venue rejected the cancel.","triggerScenarios":"Calling cancel-order with neither `txid` nor `cl_ord_id` set, or with values the builder considers invalid (empty strings, both identifiers conflicting per builder rules).","commonSituations":"Cancelling from a code path where the order was never acknowledged so no venue order id exists; empty string client order IDs passed through from order manager state; refactor changed which identifier branch populates the builder.","solutions":["Read the inner `{e}` message to see the builder's complaint.","Ensure at least one of `txid` (venue order id) or `cl_ord_id` is a non-empty string before calling cancel.","Verify the order reached the venue (has a `venue_order_id`) before issuing cancels; skip cancel for unacknowledged orders.","Log the builder inputs when this occurs to spot empty/None identifiers upstream."],"exampleFix":"// before\nlet cl_ord_id: Option<String> = order.client_order_id(); // None for unacknowledged order\n// after\nif order.venue_order_id().is_none() { return Ok(()); } // nothing to cancel\nbuilder.txid(order.venue_order_id().unwrap().to_string());","handlingStrategy":"validation","validationCode":"fn validate_cancel(venue_order_id: Option<&String>, cl_ord_id: Option<&String>) -> Result<(), String> {\n    let has_txid = venue_order_id.map_or(false, |s| !s.is_empty());\n    let has_cl = cl_ord_id.map_or(false, |s| !s.is_empty());\n    if has_txid || has_cl { Ok(()) } else { Err(\"cancel requires txid or cl_ord_id\".into()) }\n}","typeGuard":"fn has_identifier(id: &Option<String>) -> bool {\n    id.as_deref().map_or(false, |s| !s.is_empty())\n}","tryCatchPattern":"match client.cancel_order(req).await {\n    Ok(_) => (),\n    Err(e) if e.to_string().contains(\"Failed to build cancel params\") => {\n        log::warn!(\"skipping cancel, invalid params: {e}\");\n    }\n    Err(e) => return Err(e),\n}","preventionTips":["Only cancel orders that have been acknowledged by the venue","Prefer the venue order id over client order id for cancels","Check for empty-string identifiers before constructing cancel requests"],"tags":["order-cancel","params-builder","validation","kraken"],"backgroundTag":"missing-required-argument","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"}