nautechsystems/nautilus_trader · error
Market connection pool is closed; shard rollback failed: {e}
Error message
Market connection pool is closed; shard rollback failed: {e} What it means
When the pool is detected as closed during assignment (after a rejected shard attempt left `rejected_shard` set), the code attempts to close the now-orphaned shard. If that close_shard call fails, the closed-pool condition and the shard-cleanup failure are combined into this error instead of the plain closed-pool error.
Source
Thrown at crates/adapters/polymarket/src/websocket/pool.rs:610
state
.shards
.remove(&id)
.expect("new shard retained for shutdown"),
)
} else {
let handle = {
let shard = state.shards.get_mut(&id).expect("new shard present");
shard.owned += 1;
shard.handle.clone()
};
state.assignments.insert(token, id);
return Ok(Some(handle));
}
};
if let Some(shard) = rejected_shard {
if let Err(e) = self.close_shard(id, Box::new(shard)).await {
anyhow::bail!("Market connection pool is closed; shard rollback failed: {e}");
}
anyhow::bail!("Market connection pool is closed");
}
unreachable!("open pool returned from assignment")
}
fn release(&self, token: Ustr) -> ReleaseOutcome {
let mut state = self.state.lock();
let Some(id) = state.assignments.remove(&token) else {
return ReleaseOutcome::NotOwned;
};
let owned = {
let Some(shard) = state.shards.get_mut(&id) else {
return ReleaseOutcome::NotOwned;
};
shard.owned = shard.owned.saturating_sub(1);View on GitHub (pinned to 18893faf8b)
Solutions
- Treat the pool as closed regardless of the rollback error — recreate and reconnect
- Log/inspect the chained {e} for why shard cleanup failed (usually a dead connection)
- Ensure shutdown tolerates already-failed shards so rollback closes don't add noise
- Avoid concurrent disconnect and subscribe on the same pool
Defensive patterns
Strategy: try-catch
Try / catch
if let Err(e) = pool.subscribe_one(asset_id).await {
if e.to_string().contains("pool is closed") {
// chained rollback failure is informational; recreate the pool
let pool = reconnect_pool()?;
}
} Prevention
- Stop subscriptions at shutdown initiation
- Make shard cleanup tolerant of dead connections
- Own pool lifecycle in a single task
- Log chained rollback errors for diagnosis
When it happens
Trigger: Pool closes concurrently with assign(); assignment is rejected by a shard that must then be closed, and close_shard on that rejected shard returns Err (e.g., connection already dead or close task fails).
Common situations: Shutdown racing an in-flight subscribe; shard connections already broken when the rollback close runs.
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
- Polymarket market pool shutdown failed: {}
- {e}; subscription rollback failed: {close_error}
- std::mem::take(&mut self.shutdown_errors).join("; ")
- Lighter WebSocket initial connection cancelled
AI-assisted analysis of nautechsystems/nautilus_trader@18893faf8b (2026-09-08).
Data as JSON: /api/errors/b07f8bf69f06af28.
Report an issue: GitHub.