nautechsystems/nautilus_trader · error · anyhow::Error
Binance Spot public JSON stream pool shutdown began during…
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.
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
- Binance Spot public JSON stream pool shutdown began during…
- Binance Spot public JSON stream pool shutdown began during…
- Binance Spot public JSON stream pool shutdown began during…
- RTDS connection was canceled by shutdown
- Architect AX data WebSocket handler did not stop after abort
AI-assisted analysis of nautechsystems/nautilus_trader@18893faf8b (2026-09-08).
Data as JSON: /api/errors/063a44d10f7399b7.
Report an issue: GitHub.
Appendix: 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)