nautechsystems/nautilus_trader · error
failed to stop prior WebSocket handler: {e}
Error message
failed to stop prior WebSocket handler: {e} What it means
In the Deribit WebSocket client's `connect`, any leftover handler tasks from a previous connection are shut down via `finish_handler()`. This error wraps the underlying failure of that shutdown, preventing a clean reconnect. It signals the internal task-generation manager could not be transitioned into shutdown.
Source
Thrown at crates/adapters/deribit/src/websocket/client.rs:535
/// # Errors
///
/// Returns an error if the connection fails.
pub async fn connect(&mut self) -> anyhow::Result<()> {
let connect_lock = Arc::clone(&self.connect_lock);
let _connect_guard = connect_lock.lock().await;
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;View on GitHub (pinned to 18893faf8b)
Solutions
- Log the inner error `{e}` to see why finish_handler failed (hung task vs runtime issue).
- Ensure the prior session was properly disconnected before calling connect again.
- Check for concurrent connect()/disconnect() calls and serialize them with a lock.
- If the handler task is stuck, add timeouts around the blocking part of the handler loop so shutdown can complete.
- Upgrade/inspect the TaskGroup (handler_tasks) implementation if errors persist on a fresh client.
Example fix
// before let _ = client.connect().await; // after client.disconnect().await?; // ensure prior handler fully stopped let _ = client.connect().await?;
Defensive patterns
Strategy: try-catch
Validate before calling
// Rust
if client.handler_state_unclean() /* or track your own connected flag */ {
client.disconnect().await?;
} Try / catch
match client.connect().await {
Err(e) if e.to_string().contains("failed to stop prior WebSocket handler") => {
// rebuild client or retry after backoff
}
Ok(v) => v,
Err(e) => return Err(e),
} Prevention
- Always await disconnect before reconnecting.
- Serialize connect/disconnect behind one ownership point (actor/task).
- Add timeouts to reconnect loops.
- Log inner errors from anyhow chains for diagnosis.
When it happens
Trigger: Calling `connect()` while `handler_tasks` is open or non-empty (a prior session's handler still exists) and the task group's shutdown/generation handshake fails (e.g. handler task hung, generation state corrupted, runtime shutdown in progress).
Common situations: Reconnecting after an unclean disconnect where the old message-handler task never completed; calling connect concurrently from two places; tearing down the tokio runtime while the handler is still draining; a bug in TaskGroup's generation 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
- Failed to start Coinbase session generation: {e}
- failed to start WebSocket handler task generation: {e}
- failed to acquire WebSocket handler task spawner: {e}
- Failed to start Derive data session generation: {e}
- Failed to start Derive data task generation: {e}
AI-assisted analysis of nautechsystems/nautilus_trader@18893faf8b (2026-09-08).
Data as JSON: /api/errors/169949ad22dd2664.
Report an issue: GitHub.