nautechsystems/nautilus_trader · error

cancel order rejected: {reason}

Error message

cancel order rejected: {reason}

What it means

Raised when a cancel-order request is rejected by Bybit (or fails with a confirmed reason) during cancel_order. The adapter emits an OrderCancelRejected event with 'cancel-order-error: {reason}' and then bails with the venue reason.

Source

Thrown at crates/adapters/bybit/src/execution.rs:1978

                        instrument_id,
                        Some(client_order_id),
                        venue_order_id,
                    )
                    .await;

                if let Err(e) = result {
                    match classify_cancel_http_failure(&e) {
                        CommandFailure::VenueRejected(reason) => {
                            let ts_event = clock.get_time_ns();
                            emitter.emit_order_cancel_rejected_event(
                                strategy_id,
                                instrument_id,
                                client_order_id,
                                venue_order_id,
                                &format!("cancel-order-error: {reason}"),
                                ts_event,
                            );
                            anyhow::bail!("cancel order rejected: {reason}");
                        }
                        CommandFailure::NotSent(reason) => {
                            log::warn!(
                                "HTTP cancel command failed local validation for {client_order_id}: {reason}"
                            );
                        }
                        CommandFailure::Ambiguous(reason) => {
                            log::warn!(
                                "Ambiguous HTTP cancel failure for {client_order_id}, awaiting reconciliation: {reason}"
                            );
                        }
                    }
                }

                Ok(())
            });

            return Ok(());

View on GitHub (pinned to 18893faf8b)

Solutions

  1. Check current order status in the cache before cancelling; treat already-filled/cancelled as benign
  2. Handle rejection reason 'order not exists or too late to cancel' as informational rather than fatal
  3. Deduplicate cancel requests in strategy logic
  4. Reconcile order state with the venue after reconnects

Example fix

// before
client.cancel_order(&order)?; // bails if order already filled
// after
if let Some(o) = cache.order(&order.client_order_id()) && o.is_open() {
    client.cancel_order(&order)?;
} // else: nothing to cancel
Defensive patterns

Strategy: try-catch

Validate before calling

if let Some(o) = cache.order(client_order_id) {
    if !o.is_open() {
        // already filled/cancelled — nothing to cancel
        return Ok(());
    }
}

Try / catch

match exec_client.cancel_order(&order) {
    Err(e) if e.to_string().starts_with("cancel order rejected:") => {
        let reason = e.to_string();
        if reason.contains("not exists") || reason.contains("too late") {
            tracing::info!("order already closed on venue; treating cancel as no-op");
        } else {
            return Err(e);
        }
    }
    r => r?,
}

Prevention

When it happens

Trigger: Calling cancel_order when Bybit rejects the cancel — e.g. the order already filled or cancelled, unknown order ID, or the order belongs to another API key.

Common situations: Attempting to cancel an order that just filled; duplicate cancel requests; stale order state after disconnects; cancels submitted for orders from a different session/key.

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


AI-assisted analysis of nautechsystems/nautilus_trader@18893faf8b (2026-09-08). Data as JSON: /api/errors/7a5a8a363d051808. Report an issue: GitHub.