nautechsystems/nautilus_trader · error · anyhow::Error
Binance Spot public JSON stream pool shutdown began during s
Error message
Binance Spot public JSON stream pool shutdown began during subscribe
What it means
The pool observed its shutdown flag while a subscribe() call was in progress; the client rolled back by closing connections and returned this error because rollback succeeded. It guarantees no new subscriptions are added to a pool that is being torn down.
Source
Thrown at crates/adapters/binance/src/spot/websocket/public_json/client.rs:349
};
if remaining_capacity >= new_streams.len() || slot_count >= MAX_CONNECTIONS {
break;
}
let new_slot = self.create_connection(slot_count).await?;
let (slot_count, shutdown) = {
let mut slots = self.slots.lock();
let shutdown = self.signal.load(Ordering::Acquire);
slots.push(new_slot);
(slots.len(), shutdown)
};
if shutdown {
let client = self.clone();
let rollback = client.close_connections().await;
return Err(match rollback {
Ok(()) => anyhow::anyhow!(
"Binance Spot public JSON stream pool shutdown began during subscribe"
),
Err(e) => anyhow::anyhow!(
"Binance Spot public JSON stream pool shutdown began during subscribe; rollback failed: {e}"
),
});
}
log::debug!(
"Spot JSON pool slot {} connected: url={}",
slot_count - 1,
self.url
);
}
// Phase 3: stage assignments, send commands, then commit slot state.
let mut slots = self.slots.lock();
if self.signal.load(Ordering::Acquire) {View on GitHub (pinned to 18893faf8b)
Solutions
- Await all pending subscribe() futures before calling close_connections()/shutdown.
- Treat this error as benign during shutdown: check the pool's shutdown state and skip retrying if teardown was intentional.
- Reorder component stop: cancel subscription tasks first, then shut down the pool.
- If rollback errors also appear, inspect handler task lifetimes so close_connections() is only called once.
Example fix
// before
client.subscribe(streams).await?; // races shutdown
client.close_connections().await;
// after
if !client.is_shutdown() {
client.subscribe(streams).await?;
}
client.close_connections().await; Defensive patterns
Strategy: try-catch
Validate before calling
if pool.is_shutdown() {
return; // skip subscribe during shutdown
} Try / catch
match client.subscribe(streams).await {
Err(e) if e.to_string().contains("shutdown began during subscribe") => {
log::debug!("subscribe aborted by shutdown");
}
Err(e) => return Err(e),
Ok(v) => Ok(v),
} Prevention
- Sequence teardown: finish subscriptions before closing the pool.
- Gate subscribe calls on the pool's shutdown state.
- Avoid stopping the data engine while subscription requests are pending.
- Supervise subscriber tasks and cancel them before pool shutdown.
When it happens
Trigger: Calling subscribe() on the public JSON pool concurrently with close_connections()/shutdown; the shutdown flag is set after the subscription batching begins but before commands are dispatched.
Common situations: Stopping a data engine or actor while quote/kline subscription requests are still queued; application shutdown ordering where the market-data client is stopped before dependent subscribers finish subscribing.
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
- RTDS connection was canceled by shutdown
- Binance Spot public JSON stream pool shutdown began during c
- Binance Spot public JSON stream pool shutdown began during c
- Binance Spot public JSON stream pool shutdown began during s
- WS user data subscription timed out
AI-assisted analysis of nautechsystems/nautilus_trader@18893faf8b (2026-09-08).
Data as JSON: /api/errors/063a44d10f7399b7.
Report an issue: GitHub.