nautechsystems/nautilus_trader · error · anyhow::Error
Client order ID not found in cache
Error message
Client order ID not found in cache
What it means
`cancel_order` looks up the dYdX u32 client ID encoded for the Nautilus client_order_id via `self.encoder.get(...)`. If no encoding exists in the local cache, cancellation cannot build the on-chain cancel message and bails.
Source
Thrown at crates/adapters/dydx/src/execution/mod.rs:1956
}; // Cache borrow released here
log::debug!("Cancelling order {client_order_id} for instrument {instrument_id}");
let (tx_manager, broadcaster, order_builder) = match self.get_execution_components() {
Ok(components) => components,
Err(e) => {
log::error!("Failed to get execution components for cancel: {e}");
return Ok(());
}
};
let block_height = self.block_time_monitor.current_block_height() as u32;
let encoded = match self.encoder.get(&client_order_id) {
Some(enc) => enc,
None => {
log::error!("Client order ID {client_order_id} not found in cache");
anyhow::bail!("Client order ID not found in cache")
}
};
let client_id_u32 = encoded.client_id;
log::debug!(
"[CANCEL_ORDER] Nautilus '{client_order_id}' -> dYdX u32={client_id_u32} | instrument={instrument_id}"
);
// Stored flags remain authoritative after the order expires
let order_flags = self.get_order_context(client_id_u32).map_or_else(
|| {
log::warn!(
"Order context not found for {client_order_id}, deriving flags from order"
);
types::OrderLifetime::from_time_in_force(
order_time_in_force, // Using extracted value
order_expire_time, // Using extracted value
false,View on GitHub (pinned to 18893faf8b)
Solutions
- Only cancel orders submitted through the same client instance/session
- Persist and reload the client-ID encoder cache across restarts if supported
- Reconcile open orders on connect and re-register their IDs before canceling
- If the order is foreign, cancel it via venue_order_id-based paths or the dYdX API directly
Example fix
// before: cancel regardless of origin
client.cancel_order(cmd)?;
// after: skip orders not submitted this session
if encoder.contains(cmd.client_order_id) {
client.cancel_order(cmd)?;
} else {
log::warn!("{} not owned by this session; skipping", cmd.client_order_id);
} Defensive patterns
Strategy: validation
Validate before calling
if !encoder.contains(client_order_id) { return Err(anyhow!("order not owned by this session")); } Type guard
fn is_session_order(encoder: &Encoder, id: &ClientOrderId) -> bool { encoder.get(id).is_some() } Try / catch
match client.cancel_order(cmd) {
Err(e) if e.to_string().contains("not found in cache") => log::warn!("foreign/unknown order, skipping cancel"),
r => r?,
} Prevention
- Only cancel orders submitted by the same client session
- Persist encoder state across restarts if order continuity is required
- Reconcile and re-register open orders on startup before canceling
When it happens
Trigger: Canceling an order whose client_order_id was never submitted through this client instance (e.g. after a process restart with a cold cache, or an order placed by another client/session).
Common situations: Adapter restart with an empty encoder cache while the strategy still holds references to prior-session orders; reconciled venue orders not originated locally; submitting orders with a different adapter instance than the one canceling.
Understand the failure class
Background: Record Not Found Errors: "not found", RecordNotFound, and "was not found" — what they mean and how to fix them — this error's family across 28 libraries.
Related errors
- partitioned cancel failed: {}
- Cannot cancel order: not connected
- Cannot cancel orders: not connected
- slots lock poisoned
- RPC block feed active without an RPC client
AI-assisted analysis of nautechsystems/nautilus_trader@18893faf8b (2026-09-08).
Data as JSON: /api/errors/560f5610b992463c.
Report an issue: GitHub.