nautechsystems/nautilus_trader · error

failed to acquire WebSocket handler task spawner: {e}

Error message

failed to acquire WebSocket handler task spawner: {e}

What it means

`connect()` obtains a spawner from `handler_tasks` to launch the new WebSocket handler tasks. This error is thrown when the spawner cannot be acquired, meaning the task group is in a state (shut down, mid-generation) where spawning is not allowed.

Source

Thrown at crates/adapters/deribit/src/websocket/client.rs:541

        log_debug!(
            "Connecting to WebSocket: {}",
            self.url,
            color = LogColor::Blue
        );

        if !self.handler_tasks.is_open() || !self.handler_tasks.is_empty() {
            self.handler_tasks.begin_shutdown();
            self.signal.store(true, Ordering::Relaxed);
            self.finish_handler()
                .await
                .map_err(|e| anyhow::anyhow!("failed to stop prior WebSocket handler: {e}"))?;
            self.handler_tasks.start_generation().map_err(|e| {
                anyhow::anyhow!("failed to start WebSocket handler task generation: {e}")
            })?;
        }
        let handler_spawner = self.handler_tasks.spawner().map_err(|e| {
            anyhow::anyhow!("failed to acquire WebSocket handler task spawner: {e}")
        })?;

        // Reset stop signal and subscription state so callers can
        // resubscribe cleanly after a manual disconnect/connect cycle.
        self.signal.store(false, Ordering::Relaxed);
        self.subscriptions_state.clear();

        // Create message handler and channel
        let (message_handler, raw_rx) = channel_message_handler();

        // No-op ping handler: handler responds to pings directly
        // Inbound Ping frames are answered by the transport, so no ping handler is needed;
        // the reader routes them away from the message channel and the handler never sees them.

        // Configure WebSocket client
        let config = WebSocketConfig {
            url: self.url.clone(),
            headers: vec![(USER_AGENT.to_string(), NAUTILUS_USER_AGENT.to_string())],

View on GitHub (pinned to 18893faf8b)

Solutions

  1. Check the wrapped `{e}` to confirm the task-group state (closed vs wrong generation).
  2. Create a fresh Deribit WebSocket client instead of reusing a shut-down one.
  3. Avoid calling connect after shutdown/close of the client.
  4. Serialize connect calls to prevent two setups from racing generation state.
  5. If you need repeated reconnects, verify each prior disconnect completed cleanly first.

Example fix

// before
let client = DeribitWsClient::new(...);
client.disconnect().await?;
client.connect().await?; // fails if internal tasks shut down
// after
let client = DeribitWsClient::new(...); // fresh client per lifecycle
client.connect().await?;
Defensive patterns

Strategy: try-catch

Validate before calling

// Only reuse a client within its valid lifecycle; do not connect after shutdown.
if client_is_shutdown { client = DeribitWsClient::new(...)?; }

Try / catch

match client.connect().await {
    Err(e) if e.to_string().contains("handler task spawner") => {
        let mut client = DeribitWsClient::new(config).await?;
        client.connect().await?;
    }
    other => other?,
}

Prevention

When it happens

Trigger: Any call to `connect()` where `handler_tasks.spawner()` returns Err — typically the group was shut down, closed, or is in an invalid generation state after prior start_generation calls.

Common situations: Reusing a client after an explicit shutdown/close; connect invoked while another connect is mid-setup; the client was dropped from a task set that has ended its lifecycle.

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


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