nautechsystems/nautilus_trader · error

Invalid venue order ID: {id}

Error message

Invalid venue order ID: {id}

What it means

`build_cancel_replace_params` (used by the WS modify path) must convert the `ModifyOrder.venue_order_id` string into an `i64`, because Binance Spot venue order IDs are numeric integers. If the ID does not parse as an integer, the adapter bails with 'Invalid venue order ID: {id}' and the modify never reaches Binance.

Source

Thrown at crates/adapters/binance/src/spot/execution.rs:2587

    }
}

fn build_cancel_replace_params(
    cmd: &ModifyOrder,
    order: &impl Order,
    quantity: Quantity,
    use_gtd: bool,
) -> anyhow::Result<CancelReplaceOrderParams> {
    let binance_side = BinanceSide::try_from(order.order_side())?;
    let binance_order_type = order_type_to_binance_spot(order.order_type(), false)?;
    let binance_tif = time_in_force_to_binance_spot(order.time_in_force(), use_gtd)?;

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

    let client_id_str = encode_broker_id(&cmd.client_order_id, BINANCE_NAUTILUS_SPOT_BROKER_ID);

    Ok(CancelReplaceOrderParams {
        symbol: cmd.instrument_id.symbol.to_string(),
        side: binance_side,
        order_type: binance_order_type,
        cancel_replace_mode: BinanceCancelReplaceMode::StopOnFailure,
        time_in_force: Some(binance_tif),
        quantity: Some(quantity.to_string()),
        quote_order_qty: None,
        price: cmd.price.map(|p| p.to_string()),
        cancel_order_id,
        cancel_orig_client_order_id: if cancel_order_id.is_none() {
            Some(client_id_str.clone())
        } else {

View on GitHub (pinned to a4b06ed870)

Solutions

  1. Always source `venue_order_id` from the venue acknowledgment (OrderAccepted/Updated) or the cached order — never construct or transform it yourself
  2. If you carry IDs through your own layer, pass them through verbatim and verify they are numeric before live use
  3. Confirm the order actually belongs to Binance Spot and was not created by another venue's execution client

Example fix

# before
modify = ModifyOrder(
    ...,
    client_order_id=order.client_order_id,
    venue_order_id=VenueOrderId(f"BNB-{order.client_order_id}"),  # non-numeric -> Invalid venue order ID
    ...,
)

# after
modify = ModifyOrder(
    ...,
    client_order_id=order.client_order_id,
    venue_order_id=order.venue_order_id,  # numeric ID exactly as returned by Binance
    ...,
)
Defensive patterns

Strategy: validation

Validate before calling

# Python: guard before submitting a WS-path modify
venue_id = order.venue_order_id
if venue_id is not None and not str(venue_id).lstrip("-").isdigit():
    self.log.error(
        f"Refusing to modify: venue_order_id {venue_id} is not a Binance numeric ID"
    )
    return

Type guard

# Python
def is_binance_spot_venue_order_id(venue_order_id) -> bool:
    """Binance Spot venue order IDs are integer strings."""
    try:
        int(str(venue_order_id))
        return True
    except ValueError:
        return False

Try / catch

# Python: modify errors surface as rejections/events; gate on the cached order first
if order.venue_order_id is None or not is_binance_spot_venue_order_id(order.venue_order_id):
    self.log.error("venue_order_id missing or malformed; skipping modify")
    return
self.request(modify_command)

Prevention

When it happens

Trigger: A `ModifyOrder` command carrying a `venue_order_id` whose string is not a pure integer — e.g. a broker-prefixed/encoded ID, an ID minted by another venue or by a backtest/simulation, or a manually constructed ID — submitted while WS trading is active.

Common situations: Replaying simulated order objects into live trading; custom code that fabricates or decorates venue order IDs; cross-venue strategies reusing one ModifyOrder builder; modifying an order whose cached venue_order_id was written by a different adapter.

Related errors


AI-assisted analysis of nautechsystems/nautilus_trader@a4b06ed870 (2026-08-16). Data as JSON: /api/errors/e33a462893397831. Report an issue: GitHub.