nautechsystems/nautilus_trader · error · anyhow::Error
Handler not available for Spot JSON pool slot {slot_idx}: {e
Error message
Handler not available for Spot JSON pool slot {slot_idx}: {e} What it means
subscribe() sends a Subscribe command to the handler task of the selected slot via its cmd_tx channel. This error means that send failed because the slot's handler task is no longer running (channel closed), even though the slot entry still exists in the pool.
Source
Thrown at crates/adapters/binance/src/spot/websocket/public_json/client.rs:399
})?;
slot_counts[slot_idx] += 1;
if let Some(batch) = slot_batches.iter_mut().find(|(i, _)| *i == slot_idx) {
batch.1.push(stream.clone());
} else {
slot_batches.push((slot_idx, vec![stream.clone()]));
}
}
for (slot_idx, batch) in &slot_batches {
slots[*slot_idx]
.cmd_tx
.send(BinanceSpotPublicWsCommand::Subscribe {
streams: batch.clone(),
})
.map_err(|e| {
anyhow::anyhow!("Handler not available for Spot JSON pool slot {slot_idx}: {e}")
})?;
slots[*slot_idx].streams.extend(batch.iter().cloned());
}
Ok(())
}
/// Unsubscribes from stream names.
///
/// # Errors
///
/// Returns an error if command delivery fails.
pub async fn unsubscribe(&self, streams: Vec<String>) -> anyhow::Result<()> {
if streams.is_empty() {
return Ok(());
}
let _connect_guard = self.connect_lock.lock().await;View on GitHub (pinned to 18893faf8b)
Solutions
- Retry subscribe() so the pool can reconnect the dead slot via create_connection before dispatching.
- Check application logs for the handler task's exit reason (WS error, panic) and fix the root disconnect cause.
- Ensure shutdown is not concurrently tearing down handlers while subscribe() runs.
- If persistent, recreate the client/pool to rebuild all slots from scratch.
Example fix
// before
client.subscribe(streams).await?; // Err: Handler not available for slot 2
// after
match client.subscribe(streams).await {
Err(e) if e.to_string().contains("Handler not available") => {
tokio::time::sleep(Duration::from_secs(1)).await;
client.subscribe(streams).await?; // reconnects dead slot
}
r => r?,
} Defensive patterns
Strategy: retry
Try / catch
match client.subscribe(streams).await {
Err(e) if e.to_string().contains("Handler not available") => {
tokio::time::sleep(Duration::from_secs(1)).await;
client.subscribe(streams).await?; // pool reconnects dead slot
}
r => r?,
} Prevention
- Monitor handler task liveness and reconnect dead slots proactively.
- Fix root disconnect causes (network stability, keep-alive/ping configuration).
- Avoid subscribing while pool shutdown is in progress.
- Recreate the client if a slot stays dead across retries.
When it happens
Trigger: A slot's WebSocket handler task has exited (connection dropped terminally, task panicked, or pool partially shut down) and then subscribe() tries to route new streams to that dead slot.
Common situations: Network loss or Binance disconnect that permanently killed one handler while the pool bookkeeping still lists the slot; shutdown racing subscribe; a reconnect bug leaving a slot without a live handler.
Related errors
- Failed to send UpdateInstrument command: {e}
- WS user data subscription timed out
- WS setup error channel closed
- subscription confirmation failed: {e}
- invalid Derive subscription channel `{channel}`
AI-assisted analysis of nautechsystems/nautilus_trader@18893faf8b (2026-09-08).
Data as JSON: /api/errors/29c7e6214be3d774.
Report an issue: GitHub.