nautechsystems/nautilus_trader · error · anyhow::Error
batch submit orders failed
Error message
batch submit orders failed
What it means
Submitting a batch (order list) of regular orders over the OKX private WebSocket failed. ws_private.batch_submit_orders returned Err; the adapter first emits OrderRejected events for every leg when the failure is NotSent (definitely never reached OKX), or logs an 'Ambiguous batch submit failure' warning for Ambiguous/VenueRejected outcomes, then returns the error with this context.
Source
Thrown at crates/adapters/okx/src/execution.rs:2402
dispatch_state.order_identities.remove(cid);
emitter.emit_order_rejected_event(
strategy_id,
instrument_id,
*cid,
&reason,
ts_event,
false,
);
}
}
CommandFailure::Ambiguous(reason) | CommandFailure::VenueRejected(reason) => {
log::warn!(
"Ambiguous batch submit failure for {} orders on {instrument_id}, awaiting reconciliation: {reason}",
client_order_ids.len()
);
}
}
return Err(anyhow::Error::new(e).context("batch submit orders failed"));
}
Ok(())
});
Ok(())
}
fn modify_order(&self, cmd: ModifyOrder) -> anyhow::Result<()> {
if is_spread_instrument(cmd.instrument_id) {
self.emitter.emit_order_modify_rejected_event(
cmd.strategy_id,
cmd.instrument_id,
cmd.client_order_id,
cmd.venue_order_id,
"OKX spread orders do not support modify requests",
self.clock.get_time_ns(),
);View on GitHub (pinned to 18893faf8b)
Solutions
- Check the classified failure: if NotSent, all legs were rejected locally and can be safely resubmitted after fixing the cause.
- If Ambiguous/VenueRejected, wait for/run reconciliation before resubmitting — orders may have been placed, and blind resubmission can double position.
- Validate every leg with the same rules OKX enforces (price/quantity precision, post-only, trade mode) before submit_order_list.
- Ensure the private WS session is connected and authenticated; retry after reconnect if it was down.
Example fix
// before: resubmitting immediately after an ambiguous failure
trader.submit_order_list(cmd);
// after: reconcile first when outcome is unknown
match failure {
CommandFailure::NotSent(_) => trader.submit_order_list(cmd),
CommandFailure::Ambiguous(_) | CommandFailure::VenueRejected(_) => {
trader.reconcile_state(instrs).await; // then decide per-leg
}
} Defensive patterns
Strategy: retry
Validate before calling
// Validate every leg before submitting the list atomically
for order in orders.iter() {
validate_order(order, trade_mode, OrderSubmission::List)
.expect("leg invalid; list would be denied");
} Try / catch
// Distinguish NotSent (safe to resend) from Ambiguous (reconcile first)
if let Err(e) = trader.submit_order_list(cmd) {
match classify_okx_ws_failure(&e) {
CommandFailure::NotSent(_) => retry_list(cmd),
CommandFailure::Ambiguous(_) | CommandFailure::VenueRejected(_) => {
reconcile_before_resubmit();
}
}
} Prevention
- Never blind-resubmit a list after an Ambiguous failure — orders may be live.
- Pre-validate all legs so one bad leg does not poison the batch.
- Keep batch sizes within OKX WS message limits.
- Ensure WS private is connected and authenticated before list submissions.
When it happens
Trigger: submit_order_list on a non-spread instrument; ws_private.batch_submit_orders returned Err: WS disconnected (NotSent), ack timeout leaving success unknown (Ambiguous), or OKX rejecting the batch message (VenueRejected).
Common situations: Submitting multi-leg lists during WS reconnects; per-leg parameter rejections (bad price/size/post-only flags) surfacing as batch errors; sending lists larger than OKX WS batch limits; ambiguous outcomes requiring reconciliation to determine what actually landed.
Related errors
- submit order failed
- WS submit order failed: {e}
- {failure_prefix}; outcome is unknown after possible transmis
- limit_price is required for order type {order_type:?}
- handler command channel closed: {e}
AI-assisted analysis of nautechsystems/nautilus_trader@18893faf8b (2026-09-08).
Data as JSON: /api/errors/8236213460d82598.
Report an issue: GitHub.