nautechsystems/nautilus_trader · error · anyhow::Error
Failed to send order modify rejected event: {e}
Error message
Failed to send order modify rejected event: {e} What it means
Same channel-closed family as 3163: `send_order_modify_rejected` sends an `OrderEventAny::ModifyRejected` event on the provided `exec_sender` unbounded mpsc channel. Failure means the receiver is gone, so the modify-rejection cannot be delivered and the error is wrapped and returned.
Source
Thrown at crates/adapters/interactive_brokers/src/execution/core.rs:1951
ts_event: UnixNanos,
account_id: AccountId,
) -> anyhow::Result<()> {
let event = OrderModifyRejected::new(
cmd.trader_id,
cmd.strategy_id,
cmd.instrument_id,
cmd.client_order_id,
Ustr::from(reason),
UUID4::new(),
ts_event,
ts_event,
false,
cmd.venue_order_id,
Some(account_id),
);
exec_sender
.send(ExecutionEvent::Order(OrderEventAny::ModifyRejected(event)))
.map_err(|e| anyhow::anyhow!("Failed to send order modify rejected event: {e}"))
}
fn send_order_cancel_rejected(
target_order: &OrderAny,
reason: &str,
exec_sender: &tokio::sync::mpsc::UnboundedSender<ExecutionEvent>,
ts_event: UnixNanos,
account_id: AccountId,
) -> anyhow::Result<()> {
let event = OrderCancelRejected::new(
target_order.trader_id(),
target_order.strategy_id(),
target_order.instrument_id(),
target_order.client_order_id(),
Ustr::from(reason),
UUID4::new(),
ts_event,
ts_event,View on GitHub (pinned to 18893faf8b)
Solutions
- Keep the execution event receiver alive until all adapter senders are dropped; stop the adapter first during shutdown.
- Verify the exec event channel routing/wiring so the sender passed to this helper still has a live receiver.
- Log and ignore if strictly during teardown, since no consumer exists for the event anymore.
Example fix
// before
exec_sender
.send(ExecutionEvent::Order(OrderEventAny::ModifyRejected(event)))
.map_err(|e| anyhow::anyhow!("Failed to send order modify rejected event: {e}"))
// after
if let Err(e) = exec_sender.send(ExecutionEvent::Order(OrderEventAny::ModifyRejected(event))) {
log::error!("modify rejected event not delivered: {e}");
} Defensive patterns
Strategy: try-catch
Try / catch
match result {
Err(e) if e.to_string().contains("Failed to send order modify rejected event") => {
log::warn!("modify rejection not delivered (receiver closed): {e}");
}
other => other?,
} Prevention
- Sequence shutdown: cancel/modify traffic quiesced, adapter disconnected, then engine dropped.
- Route all exec events through the engine-owned sender with the receiver joined last.
- In tests, assert receivers outlive all senders (tokio mpsc semantics).
When it happens
Trigger: IB rejects an order modify request and the adapter calls `send_order_modify_rejected`, but the `exec_sender`'s receiver was dropped (event loop stopped, node tearing down, or the sender passed in belongs to a dead receiver).
Common situations: Late modify-reject arriving during shutdown; cancel-and-replace failing after the execution engine stopped; misconfigured exec routing so the receiver was closed.
Related errors
- Failed to send order denied event: {e}
- Failed to send order cancel rejected event: {e}
- Failed to send order pending cancel event: {e}
- task slot is already occupied
- failed to finish Binance Futures data command tasks: {e}
AI-assisted analysis of nautechsystems/nautilus_trader@18893faf8b (2026-09-08).
Data as JSON: /api/errors/cf69d8f92cf9766a.
Report an issue: GitHub.