nautechsystems/nautilus_trader · error

Either venue_order_id or client_order_id must be provided

Error message

Either venue_order_id or client_order_id must be provided

What it means

`modify_order` on the Binance futures HTTP client requires at least one order identifier. Binance's API accepts either `orderId` or `origClientOrderId`; if both `venue_order_id` and `client_order_id` are `None`, the adapter cannot build a valid modify request and fails fast with `anyhow::ensure!`.

Solutions

  1. Pass the `VenueOrderId` obtained from the submit response/report.
  2. Or pass the original `ClientOrderId` used at submission (it is broker-encoded automatically).
  3. Add caller-side code that stores at least one of the two identifiers on every order before any modify path can run.

Example fix

// before
client.modify_order(instrument_id, None, None, side, qty, price).await?;
// after
client.modify_order(instrument_id, Some(venue_order_id), None, side, qty, price).await?;
Defensive patterns

Strategy: validation

Validate before calling

fn ensure_modify_id(venue: Option<&VenueOrderId>, client: Option<&ClientOrderId>) -> Result<(), String> {
    if venue.is_none() && client.is_none() {
        return Err("modify_order needs venue_order_id or client_order_id".into());
    }
    Ok(())
}

Type guard

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

Try / catch

match client.modify_order(instrument_id, venue_id, client_id, side, qty, price).await {
    Err(e) if e.to_string().contains("must be provided") => {
        // look up an ID from the order cache before retrying
    }
    other => other?,
}

Prevention

When it happens

Trigger: Calling `modify_order(instrument_id, None, None, order_side, quantity, price)` — e.g. an execution layer that resolved neither identifier, or a partially constructed OrderModify command with empty IDs.

Common situations: Passing None after a failed order-ID lookup; constructing the modify call programmatically with optional IDs that were never populated; race where the client order ID was never persisted and the venue ID was not yet received.

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/01b10be98118be58. Report an issue: GitHub.

Appendix: source

Thrown at crates/adapters/binance/src/futures/http/client.rs:2391

    ///
    /// # Errors
    ///
    /// Returns an error if:
    /// - Neither venue_order_id nor client_order_id is provided.
    /// - The instrument is not cached.
    /// - The request fails.
    #[expect(clippy::too_many_arguments)]
    pub async fn modify_order(
        &self,
        account_id: AccountId,
        instrument_id: InstrumentId,
        venue_order_id: Option<VenueOrderId>,
        client_order_id: Option<ClientOrderId>,
        order_side: OrderSide,
        quantity: Quantity,
        price: Price,
    ) -> anyhow::Result<OrderStatusReport> {
        anyhow::ensure!(
            venue_order_id.is_some() || client_order_id.is_some(),
            "Either venue_order_id or client_order_id must be provided"
        );

        let (symbol, price_precision, size_precision) =
            self.cached_precisions_by_id(instrument_id)?;

        let binance_side = BinanceSide::try_from(order_side)?;

        let order_id = venue_order_id
            .map(|id| id.inner().parse::<i64>())
            .transpose()
            .map_err(|_| anyhow::anyhow!("Invalid venue order ID"))?;

        let params = BinanceModifyOrderParams {
            symbol,
            order_id,
            orig_client_order_id: client_order_id

View on GitHub (pinned to 18893faf8b)