nautechsystems/nautilus_trader · error

Either client_order_id or venue_order_id must be provided

Error message

Either client_order_id or venue_order_id must be provided

What it means

Bybit identifies orders either by its own orderId or by the client-supplied orderLinkId. The cancel-order request builder requires at least one of them; the adapter bails when both are None because the request would be invalid.

Source

Thrown at crates/adapters/bybit/src/http/client.rs:2704

        &self,
        account_id: AccountId,
        product_type: BybitProductType,
        instrument_id: InstrumentId,
        client_order_id: Option<ClientOrderId>,
        venue_order_id: Option<VenueOrderId>,
    ) -> anyhow::Result<OrderStatusReport> {
        let instrument = self.instrument_from_cache(&instrument_id.symbol)?;
        let bybit_symbol = BybitSymbol::new(instrument_id.symbol.as_str())?;

        let mut cancel_entry = BybitBatchCancelOrderEntryBuilder::default();
        cancel_entry.symbol(bybit_symbol.raw_symbol().to_string());

        if let Some(venue_order_id) = venue_order_id {
            cancel_entry.order_id(venue_order_id.to_string());
        } else if let Some(client_order_id) = client_order_id {
            cancel_entry.order_link_id(client_order_id.to_string());
        } else {
            anyhow::bail!("Either client_order_id or venue_order_id must be provided");
        }

        let cancel_entry = cancel_entry.build().build_anyhow()?;

        let mut params = BybitCancelOrderParamsBuilder::default();
        params.category(product_type);
        params.order(cancel_entry);

        let params = params.build().build_anyhow()?;
        let body = serde_json::to_vec(&params)?;

        let response: BybitPlaceOrderResponse = self
            .inner
            .send_request::<_, ()>(Method::POST, "/v5/order/cancel", None, Some(body), true)
            .await?;

        let order_id = response
            .result

View on GitHub (pinned to 18893faf8b)

Solutions

  1. Always supply the venue_order_id if the order was acknowledged by the venue
  2. Otherwise supply the client_order_id used at submission
  3. Add a caller-side check that at least one identifier is Some before invoking the client

Example fix

// before
client.cancel_order(product_type, symbol, None, None).await?;
// after
client.cancel_order(product_type, symbol, Some(venue_order_id), None).await?
Defensive patterns

Strategy: validation

Validate before calling

anyhow::ensure!(venue_order_id.is_some() || client_order_id.is_some(), "cancel needs venue_order_id or client_order_id");

Type guard

fn has_order_id(v: &Option<VenueOrderId>, c: &Option<ClientOrderId>) -> bool { v.is_some() || c.is_some() }

Try / catch

match client.cancel_order(pt, symbol, venue_id, client_id).await {
    Err(e) if e.to_string().contains("must be provided") => { /* resolve identifier from cache and retry */ }
    other => other?,
}

Prevention

When it happens

Trigger: Calling cancel_order on the Bybit HTTP client with both venue_order_id and client_order_id as None.

Common situations: A caller that lost track of the order identifiers, e.g. passing through an event where neither ID was populated; constructing cancel requests programmatically with unwrapped-then-dropped Option values.

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/2bbe148dd423c12e. Report an issue: GitHub.