nautechsystems/nautilus_trader · error

Failed to terminate Lighter tasks: {}

Error message

Failed to terminate Lighter tasks: {}

What it means

Aggregated shutdown-failure error from the Lighter execution client. finish_session_shutdown (invoked by connect on failure and by disconnect) drains shutdown_errors accumulated from finishing owned tasks (WS senders, writers, nonce manager, etc.); if any are present it bails with this message and the joined per-task errors. It signals the execution session's background tasks did not all terminate cleanly.

Source

Thrown at crates/adapters/lighter/src/execution.rs:479

        )
        .await;

        if let Err(e) = self
            .pending_tasks
            .finish_shutdown(Duration::from_secs(1), DISCONNECT_TIMEOUT)
            .await
        {
            self.shutdown_errors
                .push(format!("client-owned tasks failed: {e}"));
        }

        let stale = self.dispatch.take_pending_sendtx();
        warn_pending_sendtx_unknown(&stale, "session shutdown");
        self.nonce_recovery_inflight.store(false, Ordering::Release);

        if !self.shutdown_errors.is_empty() {
            let errors = std::mem::take(&mut self.shutdown_errors);
            anyhow::bail!("Failed to terminate Lighter tasks: {}", errors.join("; "));
        }
        Ok(())
    }

    async fn finish_owned_task(
        slot: &mut TaskSlot<()>,
        description: &str,
        errors: &mut Vec<String>,
    ) {
        let Some(outcome) = finish_task(slot, DISCONNECT_TIMEOUT, DISCONNECT_TIMEOUT).await else {
            return;
        };

        match outcome {
            TaskJoinOutcome::Completed(()) => {
                log::debug!("Lighter {description} task completed");
            }
            TaskJoinOutcome::Aborted => {

View on GitHub (pinned to 18893faf8b)

Solutions

  1. Inspect the joined error text after the prefix to identify which task failed and why.
  2. Retry disconnect(); teardown errors during an outage typically resolve once connectivity is restored and usually don't affect already-submitted orders.
  3. Check connectivity/proxy stability if this fires on every shutdown.
  4. If shutdown consistently reports errors on a healthy connection, capture the full message and file a bug with the task description listed in it.
Defensive patterns

Strategy: try-catch

Try / catch

match exec_client.disconnect().await {
    Ok(()) => {}
    Err(e) if e.to_string().starts_with("Failed to terminate Lighter tasks") => {
        tracing::warn!("execution teardown errors: {e:#}");
        // parse joined task errors; retry disconnect if network was down
    }
    Err(e) => return Err(e),
}

Prevention

When it happens

Trigger: Calling disconnect() on the Lighter execution client (or connect() aborting partway) while one or more owned tasks returned an error on completion - e.g. WS send channel already closed, writer task failed on a broken transport, or a task panicked.

Common situations: Disconnecting while an order submission is in flight and the writer task errors; network outage during teardown; repeated reconnect cycles leaving errored task handles; nonce manager task failing during shutdown.

Related errors


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