nautechsystems/nautilus_trader · error · anyhow::Error

Failed to send execution report: {e}

Error message

Failed to send execution report: {e}

What it means

try_send_execution_report had a sender, but the channel send failed because the receiver side was dropped/closed. The underlying channel error is included. The execution event consumer is no longer accepting reports.

Source

Thrown at crates/live/src/execution/emitter.rs:524

    pub fn send_execution_report(&self, report: ExecutionReport) {
        if let Err(e) = self.try_send_execution_report(report) {
            log::warn!("{e}");
        }
    }

    /// Emits an execution report and returns any channel error to the caller.
    ///
    /// # Errors
    ///
    /// Returns an error if the sender is not initialized or the receiving channel is closed.
    pub fn try_send_execution_report(&self, report: ExecutionReport) -> anyhow::Result<()> {
        let sender = self.sender.load();
        let sender = sender.as_ref().ok_or_else(|| {
            anyhow::anyhow!("Cannot send execution report: sender not initialized")
        })?;
        sender
            .send(ExecutionEvent::Report(report))
            .map_err(|e| anyhow::anyhow!("Failed to send execution report: {e}"))
    }

    /// Emits an order status report.
    pub fn send_order_status_report(&self, report: OrderStatusReport) {
        self.send_execution_report(ExecutionReport::Order(Box::new(report)));
    }

    /// Emits a fill report.
    pub fn send_fill_report(&self, report: FillReport) {
        self.send_execution_report(ExecutionReport::Fill(Box::new(report)));
    }

    /// Emits an order status report bundled with the fills that produced it.
    pub fn send_order_with_fills(&self, report: OrderStatusReport, fills: Vec<FillReport>) {
        self.send_execution_report(ExecutionReport::OrderWithFills(Box::new(report), fills));
    }

    /// Emits a position status report.

View on GitHub (pinned to 18893faf8b)

Solutions

  1. Halt report emission once shutdown begins; drop or log late messages.
  2. Wait for reconnect to re-establish the channel before re-emitting.
  3. Log at warn during teardown races instead of failing hard.
  4. Inspect the embedded channel error to confirm the receiver-closed cause.

Example fix

// before
emitter.try_send_execution_report(report)?;
// after
if let Err(e) = emitter.try_send_execution_report(report) {
    log::warn!("execution report dropped (receiver closed): {e}");
}
Defensive patterns

Strategy: try-catch

Try / catch

if let Err(e) = emitter.try_send_execution_report(report) { log::warn!("report dropped (receiver closed): {e}"); }

Prevention

When it happens

Trigger: Emitting execution reports after the execution engine receiver was torn down — during shutdown, engine restart, or after the consuming task exited (crash/panic).

Common situations: Late venue fill/status messages arriving during node teardown; reconnect handlers emitting stale reports while the engine is restarting.

Related errors


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