nautechsystems/nautilus_trader · error

errors joined with "; " (aggregated disconnect errors)

Error message

errors joined with "; " (aggregated disconnect errors)

What it means

The execution (trading) client has its own teardown_partial_connect used on disconnect and failed connects. It shuts down session/pending tasks and, if any step produced an error, returns them aggregated as one message joined by "; ". It indicates the trading connection did not tear down cleanly.

Source

Thrown at crates/adapters/deribit/src/execution.rs:236

        if let Err(e) = self.ws_client.close().await {
            errors.push(format!("WebSocket shutdown failed: {e}"));
        }
        let (session_result, pending_result) =
            tokio::join!(self.await_session_tasks(), self.await_pending_tasks());

        if let Err(e) = session_result {
            errors.push(e.to_string());
        }

        if let Err(e) = pending_result {
            errors.push(e.to_string());
        }
        self.core.set_disconnected();

        if errors.is_empty() {
            Ok(())
        } else {
            anyhow::bail!(errors.join("; "))
        }
    }

    // Rejects unsupported order types and time-in-force values
    fn build_order_params(order: &dyn Order) -> anyhow::Result<DeribitOrderParams> {
        let order_type = match order.order_type() {
            OrderType::Limit => "limit",
            OrderType::Market => "market",
            OrderType::StopLimit => "stop_limit",
            OrderType::StopMarket => "stop_market",
            OrderType::LimitIfTouched => "take_limit",
            OrderType::MarketIfTouched => "take_market",
            other => {
                anyhow::bail!("Unsupported order type {other:?} for Deribit");
            }
        }
        .to_string();

View on GitHub (pinned to 18893faf8b)

Solutions

  1. Parse each "; "-separated segment to find the concrete failing teardown step
  2. Check Deribit API connectivity and credentials before reconnecting
  3. Avoid disconnecting while order tasks are pending; await/drain pending tasks first
  4. Inspect TaskGroupGuard shutdown logic if a task join consistently hangs or errors

Example fix

// before
match client.disconnect().await { _ => {} }
// after
if let Err(e) = client.disconnect().await {
    e.to_string().split("; ").for_each(|c| tracing::error!(%c, "teardown"));
}
Defensive patterns

Strategy: try-catch

Validate before calling

// Drain pending order tasks before teardown
assert!(pending_tasks_done(), "await pending order tasks before disconnect");

Try / catch

if let Err(e) = exec_client.disconnect().await {
    e.to_string().split("; ").for_each(|c| log::error!("exec teardown: {c}"));
}

Prevention

When it happens

Trigger: Calling exec client disconnect(), or connect() failing partway (credentials/auth/WS setup), so teardown runs and any task shutdown or channel close errors are collected into a non-empty errors vec.

Common situations: Open orders with pending tasks at disconnect; WS already dead after a network drop so shutdown signaling fails; auth failure during connect leaving partially initialized state; double disconnect.

Related errors


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