nautechsystems/nautilus_trader · error · anyhow::Error
Failed to send order rejected event: {e}
Error message
Failed to send order rejected event: {e} What it means
After a what-if order analysis completes, the adapter builds an OrderRejected/Denied event and sends it through the exec_sender channel. The send fails when the execution event receiver has been dropped, meaning the engine consuming events is gone while the IB what-if response is being processed.
Source
Thrown at crates/adapters/interactive_brokers/src/execution/core_updates.rs:1103
.unwrap_or_else(|_| format!("whatIf analysis for order {}", order_data.order_id));
let event = OrderRejected::new(
trader_id,
strategy_id,
instrument_id,
client_order_id,
account_id,
Ustr::from(&reason_json),
UUID4::new(),
ts_init,
ts_init,
false,
false,
);
exec_sender
.send(ExecutionEvent::Order(OrderEventAny::Rejected(event)))
.map_err(|e| anyhow::anyhow!("Failed to send order rejected event: {e}"))?;
tracing::debug!(
"What-if analysis completed for order {}: margin change={:?}, commission={:?}",
client_order_id,
order_data
.order_state
.initial_margin_after
.and_then(|after| order_data
.order_state
.initial_margin_before
.map(|before| after - before)),
order_data.order_state.commission
);
Ok(())
}
#[allow(clippy::too_many_arguments)]View on GitHub (pinned to 18893faf8b)
Solutions
- Keep the execution engine/event consumer running until IB what-if responses are drained or the adapter disconnects.
- Stop what-if requests and adapter subscriptions before shutting down the event receiver.
- Log send failures during shutdown rather than treating them as fatal.
Example fix
// before
exec_sender
.send(ExecutionEvent::Order(OrderEventAny::Rejected(event)))
.map_err(|e| anyhow::anyhow!("Failed to send order rejected event: {e}"))?;
// after
if let Err(e) = exec_sender.send(ExecutionEvent::Order(OrderEventAny::Rejected(event))) {
tracing::warn!("Execution channel closed, dropping what-if rejected event: {e}");
} Defensive patterns
Strategy: try-catch
Validate before calling
// Rust: only send what-if events while the channel is open
if exec_sender.is_closed() {
tracing::warn!("Channel closed; what-if rejected event dropped");
return Ok(());
} Type guard
fn channel_open(sender: &mpsc::Sender<ExecutionEvent>) -> bool {
!sender.is_closed()
} Try / catch
if let Err(e) = exec_sender.send(ExecutionEvent::Order(OrderEventAny::Rejected(event))) {
tracing::warn!("What-if rejected event dropped: {e}");
return Ok(());
} Prevention
- Await what-if responses before shutting down the execution engine
- Cancel outstanding what-if requests on disconnect
- Treat post-shutdown send failures as warnings, not errors
When it happens
Trigger: handle_whatif_order receives an OpenOrder/OrderState for a what-if order, emits OrderEventAny::Rejected via exec_sender.send, and the channel receiver is closed.
Common situations: Engine/node shut down while what-if results stream back; consumer task died from an earlier fault; adapter still subscribed after teardown.
Related errors
- Failed to send order updated event: {e}
- Failed to send order canceled event: {e}
- failed to request logging sync: {e}
- failed to receive logging sync acknowledgement: {e}
- Failed to send delete order command: {e}
AI-assisted analysis of nautechsystems/nautilus_trader@18893faf8b (2026-09-08).
Data as JSON: /api/errors/e2b856d0b0837aeb.
Report an issue: GitHub.