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

  1. Keep the execution event receiver alive until all adapter senders are dropped; stop the adapter first during shutdown.
  2. Verify the exec event channel routing/wiring so the sender passed to this helper still has a live receiver.
  3. 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

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


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