nautechsystems/nautilus_trader · error
submit order rejected: {reason}
Error message
submit order rejected: {reason} What it means
Raised when a submit-order request reaches Bybit but the venue rejects it, or the request fails with a confirmed rejection reason. The adapter emits an OrderRejected event (flagging post-only rejections) and then fails the submit_order call with the venue's reason.
Source
Thrown at crates/adapters/bybit/src/execution.rs:1411
smp_type,
native_tp_sl_ref,
)
.await;
if let Err(e) = result {
if let Some(reason) = submit_rejection_reason(&e) {
dispatch_state.order_identities.remove(&client_order_id);
dispatch_state.order_snapshots.remove(&client_order_id);
let ts_event = clock.get_time_ns();
emitter.emit_order_rejected_event(
strategy_id,
instrument_id,
client_order_id,
reason,
ts_event,
bybit_rejection_due_post_only(reason),
);
anyhow::bail!("submit order rejected: {reason}");
}
log::warn!(
"Submit failure without confirmed venue rejection for {client_order_id}: \
{e}; awaiting reconciliation",
);
return Ok(());
}
Ok(())
});
return Ok(());
}
let raw_symbol = extract_raw_symbol(instrument_id.symbol.as_str());
let params = Self::build_ws_place_params(
&order,View on GitHub (pinned to 18893faf8b)
Solutions
- Read the rejection reason in the error/OrderRejected event and correct the order parameters
- Check account balance and symbol filters (min qty, tick size, notional) before submitting
- Avoid postOnly for orders likely to cross, or handle post-only rejections with re-pricing/retry logic
- Verify the instrument is tradeable and the API key has trading permissions
Example fix
// before
client.submit_order(post_only_limit_that_crosses)?; // bail: submit order rejected
// after
match client.submit_order(order) {
Err(e) if bybit_rejection_due_post_only(&e) => {
let taker = order.as_limit().set_post_only(false);
client.submit_order(taker)?;
}
result => result?,
} Defensive patterns
Strategy: try-catch
Validate before calling
let instrument = cache.instrument(&order.instrument_id()).unwrap(); let price = order.as_limit().price(); let qty = order.quantity(); assert!(qty >= instrument.min_quantity().unwrap(), "qty below min"); assert!(price % instrument.tick_size() == 0.0, "price off tick size"); // check balance >= qty * price for buys before submitting
Try / catch
match exec_client.submit_order(order) {
Err(e) if e.to_string().starts_with("submit order rejected:") => {
let reason = e.to_string();
if reason.contains("post-only") {
// re-price as taker or drop the order
} else {
// handle balance/filter rejections
}
}
r => r?,
} Prevention
- Validate price/qty against the instrument's filters before submit
- Keep sufficient balance buffer for buy orders
- Handle post-only rejections with re-pricing logic
- Confirm trading permissions on the API key
When it happens
Trigger: Calling submit_order when Bybit responds with a rejection reason — e.g. insufficient balance, post-only would cross the book, invalid price/qty filters, or order already exists.
Common situations: Post-only limit orders that would immediately execute; order sizes below the venue's min notional/qty; price outside allowed bounds; trading a symbol while the account lacks funds or permissions.
Understand the failure class
Background: "API error: {status}" and "HTTP 401/403/404/429/5xx" errors: non-2xx HTTP responses explained — this error's family across 27 libraries.
Related errors
- modify order rejected: {reason}
- cancel order rejected: {reason}
- Batch cancel limit is {endpoint_limit} orders for {product_t
- Order rejected: {reason}
- Order modification rejected: {reason}
AI-assisted analysis of nautechsystems/nautilus_trader@18893faf8b (2026-09-08).
Data as JSON: /api/errors/77db5ec3e80242a8.
Report an issue: GitHub.