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
- Always source `venue_order_id` from the venue acknowledgment (OrderAccepted/Updated) or the cached order — never construct or transform it yourself
- If you carry IDs through your own layer, pass them through verbatim and verify they are numeric before live use
- 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
- Never fabricate, prefix, or reformat venue_order_id — pass through the exact string Binance assigned
- Source venue_order_id from the venue acknowledgment event or the cache, not from your own ID scheme
- Validate that IDs are numeric in any persistence layer that round-trips orders between environments (sim → live)
- Keep one ModifyOrder construction path per venue to avoid cross-venue ID mixups
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
- venue_order_id required for modify
- WS modify order failed: {e}
- Conditional orders require a trigger price
- height must be positive, was {self.height}
- AX instrument product must be non-empty without surrounding
AI-assisted analysis of nautechsystems/nautilus_trader@a4b06ed870 (2026-08-16).
Data as JSON: /api/errors/e33a462893397831.
Report an issue: GitHub.