nautechsystems/nautilus_trader · error
{reason}
Error message
{reason} What it means
During `cancel_algo_order` (invoked from `cancel_order`), the adapter's HTTP cancel path reports a rejection reason for the algo-order cancel request; if `is_rejected` is true, the adapter aborts with the venue-provided `{reason}` as the error message. This means OKX itself refused the algo cancel, not the adapter.
Source
Thrown at crates/adapters/okx/src/execution.rs:1096
(code != OKX_SUCCESS_CODE)
.then_some((code, r.s_msg.as_deref().unwrap_or("unknown")))
})
}) {
let reason =
format!("cancel-algo-order-rejected: s_code={code}, s_msg={msg}");
let failure = classify_okx_venue_code(code, reason.clone());
let is_rejected = matches!(failure, CommandFailure::VenueRejected(_));
emit_cancel_failure(
failure,
Some((&emitter, clock)),
command.client_order_id,
command.instrument_id,
command.strategy_id,
command.venue_order_id,
);
if is_rejected {
anyhow::bail!("{reason}");
}
}
}
}
Ok(())
});
}
fn mass_cancel_instrument(&self, instrument_id: InstrumentId) {
if is_spread_instrument(instrument_id) {
let http_client = self.http_client.clone();
self.spawn_task("mass_cancel_orders_http", async move {
if let Err(e) = http_client.cancel_all_orders(instrument_id).await {
log_mass_cancel_failure(classify_okx_http_failure(&e), instrument_id);
return Err(anyhow::Error::new(e).context("mass cancel orders failed"));
}
Ok(())View on GitHub (pinned to 18893faf8b)
Solutions
- Read the embedded `{reason}` text — it is OKX's own rejection message (commonly 'order already canceled' or 'order has been filled').
- Check the order's current state in the cache before issuing a cancel; skip cancel if already closed/filled.
- Make cancel handling idempotent: treat 'already canceled/filled' rejections as success in your reconciliation logic.
- Retry with a fresh `venue_order_id` if the ID was stale after a session re-establishment.
Defensive patterns
Strategy: try-catch
Validate before calling
if let Some(order) = cache.order_for_venue(&venue_order_id) {
if order.is_closed() {
return Ok(()); // nothing to cancel
}
} Try / catch
match client.cancel_order(cmd) {
Err(e) if e.to_string().contains("already canceled") || e.to_string().contains("filled") => {
log::warn!("cancel rejected as already closed: {e}"); // treat as idempotent success
}
Err(e) => return Err(e),
Ok(()) => {}
} Prevention
- Check cached order state before issuing algo cancels.
- Make cancel flows idempotent — duplicate or late cancels are normal.
- Log the full venue reason string; it identifies whether the order filled or was already canceled.
When it happens
Trigger: Calling `cancel_order` for an algo order where the OKX cancel response marks the result as rejected; the raw OKX reason string (e.g. order already filled/canceled, invalid algo ID, order not found) becomes the error text.
Common situations: Race condition where the trigger order fires (fills) just before the cancel arrives; canceling with a stale `venue_order_id` after a reconnect; duplicate cancel requests.
Related errors
- cancel order rejected: {reason}
- Order cancellation failed: {status}
- Unsupported OKX algo order status: {e}
- cancel algo order failed
- modify order failed
AI-assisted analysis of nautechsystems/nautilus_trader@18893faf8b (2026-09-08).
Data as JSON: /api/errors/fa89352bff8511c7.
Report an issue: GitHub.