nautechsystems/nautilus_trader · error · anyhow::Error
Cannot send execution report: sender not initialized
Error message
Cannot send execution report: sender not initialized
What it means
Raised by try_send_execution_report when the emitter's sender slot is still None: an ExecutionReport (order status, fills, etc.) cannot be routed because the execution event channel was never wired. This is a lifecycle/ordering violation in the live execution pipeline.
Source
Thrown at crates/live/src/execution/emitter.rs:520
.map_err(|e| anyhow::anyhow!("Failed to send account state: {e}"))
}
/// Emits an execution report.
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>) {View on GitHub (pinned to 18893faf8b)
Solutions
- Complete the emitter/engine initialization before processing any venue messages.
- Buffer incoming reports until the emitter is ready, then flush in order.
- Verify adapter message handlers are only registered/active after the engine start sequence.
- If it happens in a running node, this indicates an internal bug — capture a repro and report it.
Example fix
// before
emitter.send_order_status_report(report);
// after
if emitter.is_initialized() {
emitter.send_order_status_report(report);
} else {
pending_reports.push(report); // flush after init
} Defensive patterns
Strategy: validation
Validate before calling
if !emitter.is_initialized() { pending_reports.push(report); return; } Type guard
fn emitter_ready(emitter: &ExecutionEmitter) -> bool { emitter.is_initialized() } Try / catch
if let Err(e) = emitter.try_send_execution_report(report) { log::error!("execution report send failed: {e}"); } Prevention
- Only subscribe adapter message handlers after engine startup
- Buffer early venue reports and flush once initialized
- Reproduce startup races with integration tests
When it happens
Trigger: Calling try_send_execution_report (directly or via send_execution_report, send_order_status_report, etc., or commit_post_reconnect_mass_status) before the emitter is initialized.
Common situations: Adapters producing execution reports from venue WebSocket messages that arrive before engine startup completes; mass-status reconciliation after reconnect racing the emitter init; unit/custom integration harnesses forgetting to start the emitter.
Understand the failure class
Background: "Invalid state transition" errors: "status must be X, actually Y", "already rejected/charging/uninstalled", "cannot ... while running" — what they mean when a library rejects your call — this error's family across 31 libraries.
Related errors
- Cannot send order event: sender not initialized
- Cannot send account state: sender not initialized
- Failed to send execution report: {e}
- Active execution intent {intent_id} was not found
- DataActor {} must be registered before calling `clock_mut()`
AI-assisted analysis of nautechsystems/nautilus_trader@18893faf8b (2026-09-08).
Data as JSON: /api/errors/1fae052c05c1b142.
Report an issue: GitHub.