nautechsystems/nautilus_trader · critical · anyhow::Error
WS submit order failed: {e}
Error message
WS submit order failed: {e} What it means
Raised inside the spawned submit_order_ws task when the Binance WebSocket API place_order_with_id call fails for an order routed to WS submission. The client removes the order's entry from pending_requests, logs 'WS submit request failed for {client_order_id}', and bails with this message carrying the underlying WS error. submit_order itself already returned Ok, so the failure surfaces asynchronously through the task/log and order-event flow rather than as a synchronous error.
Source
Thrown at crates/adapters/binance/src/futures/execution.rs:667
// Pre-register before sending to avoid response racing the insert
let request_id = ws_client.next_request_id();
dispatch_state.pending_requests.insert(
request_id.clone(),
PendingRequest {
client_order_id,
venue_order_id: None,
operation: PendingOperation::Place,
},
);
self.spawn_task("submit_order_ws", async move {
if let Err(e) = ws_client
.place_order_with_id(request_id.clone(), params)
.await
{
dispatch_state.pending_requests.remove(&request_id);
log::error!("WS submit request failed for {client_order_id}: {e}");
anyhow::bail!("WS submit order failed: {e}");
}
Ok(())
});
return Ok(());
}
let http_client = self.http_client.clone();
self.spawn_task("submit_order", async move {
let result = if use_algo_api {
http_client
.submit_algo_order(
account_id,
instrument_id,
client_order_id,
order_side,
order_type,View on GitHub (pinned to a4b06ed870)
Solutions
- Read the embedded WS error code in the logged {e} (filter names like PERCENT_PRICE_BY_SIDE or -2019 insufficient margin) and correct the offending field
- Round price and quantity to the instrument's price/size precision from the cached instrument definitions
- Throttle submissions to the venue's order rate limits (max_order_submit_rate config)
- If WS errors persist, verify connection health or route submissions over HTTP if the client configuration allows it
Defensive patterns
Strategy: try-catch
Validate before calling
use nautilus_model::types::fixed::FixedPrecision; // conceptual // Pre-submit against cached instrument filters: let f = instrument_filters(instrument_id); anyhow::ensure!(qty >= f.min_qty && price >= f.min_price && (price * qty) >= f.min_notional); anyhow::ensure!(price % f.tick_size == 0 && qty % f.step_size == 0);
Try / catch
// submit_order returns Ok; the WS failure is async. Handle it via order events: // match OrderEvent for this client_order_id — // OrderDenied/OrderRejected => read the logged 'WS submit request failed' error, // correct fields (precision, notional, margin) or back off, then resubmit once. // never blind-retry on filter rejections (-4xxx / -2021 family)
Prevention
- Round price/size to instrument precision before submitting
- Respect max_order_submit_rate and the venue's order rate limits
- Watch WS connection state and pause submissions during reconnects
- Log and alert on every 'WS submit request failed' line; it means no order reached the venue
When it happens
Trigger: Submitting over the Binance futures WS order channel an order that violates exchange filters (PRICE_FILTER, LOT_SIZE, MIN_NOTIONAL), exceeds available margin, hits the order rate limit, or is sent while the WS connection is closed or reconnecting.
Common situations: High-frequency strategies exceeding max_order_submit_rate; prices/quantities rounded to strategy-side precision instead of the instrument's precision; WS session dropped during volatility and submissions continuing on the stale connection.
Related errors
- WS cancel order failed: {e}
- BacktestNode state is unavailable when dispose_on_completion
- Timeout waiting for account {account_id} to be registered af
- noid '{}' does not match new order oid '{}'
- Binance historical bars require time aggregation
AI-assisted analysis of nautechsystems/nautilus_trader@a4b06ed870 (2026-08-16).
Data as JSON: /api/errors/840350edf2a3ef1b.
Report an issue: GitHub.