nautechsystems/nautilus_trader · error
modify order rejected: {reason}
Error message
modify order rejected: {reason} What it means
Raised when a modify-order request is rejected by Bybit (or fails with a confirmed reason) during modify_order. The adapter emits an OrderModifyRejected event carrying 'modify-order-error: {reason}' and then bails with the venue reason.
Source
Thrown at crates/adapters/bybit/src/execution.rs:1858
venue_order_id,
quantity,
price,
)
.await;
if let Err(e) = result {
match classify_modify_http_failure(&e) {
CommandFailure::VenueRejected(reason) => {
let ts_event = clock.get_time_ns();
emitter.emit_order_modify_rejected_event(
strategy_id,
instrument_id,
client_order_id,
venue_order_id,
&format!("modify-order-error: {reason}"),
ts_event,
);
anyhow::bail!("modify order rejected: {reason}");
}
CommandFailure::NotSent(reason) => {
log::warn!(
"HTTP modify command failed local validation for {client_order_id}: {reason}"
);
}
CommandFailure::Ambiguous(reason) => {
log::warn!(
"Ambiguous HTTP modify failure for {client_order_id}, awaiting reconciliation: {reason}"
);
}
}
}
Ok(())
});
return Ok(());View on GitHub (pinned to 18893faf8b)
Solutions
- Check the order is still open (not filled/cancelled) before modifying
- Validate new price/qty against the instrument's tick size and lot size before calling
- Handle the rejection reason and fall back to cancel+replace if modify is not possible
- Refresh order state via reconciliation if venue order IDs are stale
Example fix
// before
client.modify_order(&order, Some(new_price), Some(new_qty))?; // may bail if order filled
// after
if let Some(order) = cache.order(client_order_id) && order.is_open() {
client.modify_order(&order, Some(new_price), Some(new_qty))?;
} else {
log::warn!("skipping modify, order not open");
} Defensive patterns
Strategy: try-catch
Validate before calling
if let Some(o) = cache.order(&venue_order_id_or_client_id) {
if !o.is_open() { return Err(anyhow!("cannot modify non-open order")); }
}
assert!(new_qty >= instrument.min_quantity().unwrap());
assert!(new_price % instrument.tick_size() == 0.0); Try / catch
match exec_client.modify_order(&order, new_price, new_qty) {
Err(e) if e.to_string().starts_with("modify order rejected:") => {
// fall back to cancel + replace
exec_client.cancel_order(&order).ok();
exec_client.submit_order(order_factory.limit(...))?;
}
r => r?,
} Prevention
- Confirm the order is still open before amending (fills/cancels race)
- Prefer cancel+replace for large state changes or when modify is uncertain
- Validate amended values against tick/lot size filters
- Reconcile venue order state before batch modifies
When it happens
Trigger: Calling modify_order when Bybit rejects the amend — e.g. order already filled or cancelled, quantity/price violating filters, unknown order ID, or modifying an order in a non-amendable state.
Common situations: Race conditions where the order fills while the modify is in flight; amend requests exceeding symbol limits; stale client/venue order IDs after reconciliation gaps.
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
- submit order rejected: {reason}
- cancel order rejected: {reason}
- modify order failed
- Batch cancel limit is {endpoint_limit} orders for {product_t
- WS modify order failed: {e}
AI-assisted analysis of nautechsystems/nautilus_trader@18893faf8b (2026-09-08).
Data as JSON: /api/errors/5eca2440008a03fe.
Report an issue: GitHub.