nautechsystems/nautilus_trader · error

{errors.join("; ")}

Error message

{errors.join("; ")}

What it means

close_shard collects per-shard shutdown errors accumulated in the pool state (shutdown_errors) and, instead of returning them one by one, joins them with '; ' into a single anyhow error. The message is thus a list of every error encountered while shutting down the shard's tasks/streams.

Source

Thrown at crates/adapters/polymarket/src/websocket/pool.rs:800

                false
            }
        };

        if let Err(e) = close.shard_mut().client.disconnect().await {
            let error = format!("market shard {id} disconnect failed: {e}");
            self.state.lock().shutdown_errors.push(error);
        }

        if forwarder_stopped && !close.shard_mut().client.has_task() {
            close.complete();
        }

        let errors = std::mem::take(&mut self.state.lock().shutdown_errors);

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

    #[cfg(test)]
    fn subscription_count_for_test(&self) -> usize {
        self.state.lock().assignments.len()
    }
}

fn should_forward_from_shard(message: &PolymarketWsMessage, is_primary: bool) -> bool {
    is_primary
        || !matches!(
            message,
            PolymarketWsMessage::Market(
                MarketWsMessage::NewMarket(_) | MarketWsMessage::MarketResolved(_)
            )
        )
}

View on GitHub (pinned to 18893faf8b)

Solutions

  1. Read each '; '-separated segment of the message — each is an individual shutdown error; address root causes individually
  2. Check whether the shard's forwarder task exited with an unexpected error (e.g. network reset) and add retry/backoff for reconnects
  3. Ensure tasks are awaited/joined properly on close so errors are not induced by premature drops
  4. If errors are benign teardown noise (e.g. connection closed by peer), filter or log-and-continue upstream rather than failing
Defensive patterns

Strategy: try-catch

Try / catch

if let Err(e) = pool.close_shard(id, shard).await {
    for err in e.to_string().split("; ") {
        log::error!("shard shutdown error: {err}");
    }
    // decide: fail hard, or continue teardown
}

Prevention

When it happens

Trigger: Calling close_shard (directly or via subscribe_one, unsubscribe_one, assign, or pool shutdown) when the shard's forwarder or underlying connection recorded one or more shutdown errors in state.shutdown_errors.

Common situations: Underlying websocket task panicked or returned an error during close; multiple streams failed to end cleanly; cascading failures during teardown after a network drop.

Related errors


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