nautechsystems/nautilus_trader · error

Failed to build cancel params: {e}

Error message

Failed to build cancel params: {e}

What it means

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.

Source

Thrown at crates/adapters/kraken/src/http/spot/client.rs:2957

        let txid = venue_order_id.as_ref().map(|id| id.to_string());
        let cl_ord_id = client_order_id.as_ref().map(truncate_cl_ord_id);

        if txid.is_none() && cl_ord_id.is_none() {
            anyhow::bail!("Either client_order_id or venue_order_id must be provided");
        }

        // Prefer txid (venue identifier) since Kraken always knows it.
        // cl_ord_id may not be known to Kraken for reconciled orders.
        let mut builder = KrakenSpotCancelOrderParamsBuilder::default();

        if let Some(ref id) = txid {
            builder.txid(id.clone());
        } else if let Some(ref id) = cl_ord_id {
            builder.cl_ord_id(id.clone());
        }
        let params = builder
            .build()
            .map_err(|e| anyhow::anyhow!("Failed to build cancel params: {e}"))?;

        self.inner.cancel_order(&params).await?;

        Ok(())
    }

    /// Cancels multiple orders on the Kraken Spot exchange (batched, max 50 per request).
    pub async fn cancel_orders_batch(
        &self,
        venue_order_ids: Vec<VenueOrderId>,
    ) -> anyhow::Result<i32> {
        if venue_order_ids.is_empty() {
            return Ok(0);
        }

        let mut total_cancelled = 0;

        for chunk in venue_order_ids.chunks(BATCH_CANCEL_LIMIT) {

View on GitHub (pinned to 18893faf8b)

Solutions

  1. Read the inner `{e}` message to see the builder's complaint.
  2. Ensure at least one of `txid` (venue order id) or `cl_ord_id` is a non-empty string before calling cancel.
  3. Verify the order reached the venue (has a `venue_order_id`) before issuing cancels; skip cancel for unacknowledged orders.
  4. Log the builder inputs when this occurs to spot empty/None identifiers upstream.

Example fix

// before
let cl_ord_id: Option<String> = order.client_order_id(); // None for unacknowledged order
// after
if order.venue_order_id().is_none() { return Ok(()); } // nothing to cancel
builder.txid(order.venue_order_id().unwrap().to_string());
Defensive patterns

Strategy: validation

Validate before calling

fn validate_cancel(venue_order_id: Option<&String>, cl_ord_id: Option<&String>) -> Result<(), String> {
    let has_txid = venue_order_id.map_or(false, |s| !s.is_empty());
    let has_cl = cl_ord_id.map_or(false, |s| !s.is_empty());
    if has_txid || has_cl { Ok(()) } else { Err("cancel requires txid or cl_ord_id".into()) }
}

Type guard

fn has_identifier(id: &Option<String>) -> bool {
    id.as_deref().map_or(false, |s| !s.is_empty())
}

Try / catch

match client.cancel_order(req).await {
    Ok(_) => (),
    Err(e) if e.to_string().contains("Failed to build cancel params") => {
        log::warn!("skipping cancel, invalid params: {e}");
    }
    Err(e) => return Err(e),
}

Prevention

When it happens

Trigger: 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).

Common situations: 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.

Understand the failure class

Background: "missing required argument" and "the following required arguments were not provided": what required-argument errors mean and how to fix them — this error's family across 20 libraries.

Related errors


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