nautechsystems/nautilus_trader · error · anyhow::Error
Failed to start Polymarket session generation: {e}
Error message
Failed to start Polymarket session generation: {e} What it means
`connect_client` similarly restarts the session task group (WebSocket dispatch, polling) via `session_tasks.start_generation()` when it is not open. Failure of that restart — because the previous generation is still terminating or the group rejects a new generation — is wrapped in this error. Note the message says 'session generation' vs 'task generation' for the pending group (error 3554).
Source
Thrown at crates/adapters/polymarket/src/execution/lifecycle.rs:652
}
log::info!("Connecting Polymarket execution client");
if !self.pending_tasks.is_open() || !self.session_tasks.is_open() {
self.teardown_partial_connect().await?;
}
if !self.pending_tasks.is_open() {
self.await_pending_tasks().await?;
self.pending_tasks
.start_generation()
.map_err(|e| anyhow::anyhow!("Failed to start Polymarket task generation: {e}"))?;
}
if !self.session_tasks.is_open() {
self.await_session_tasks().await?;
self.session_tasks.start_generation().map_err(|e| {
anyhow::anyhow!("Failed to start Polymarket session generation: {e}")
})?;
}
self.stopping.store(false, Ordering::Release);
let ws_shutdown = self.ws_client.shutdown_handle();
let stopping = Arc::clone(&self.stopping);
let setup_guard =
TaskGroupGuard::new(&[&self.session_tasks, &self.pending_tasks], move || {
stopping.store(true, Ordering::Release);
ws_shutdown.begin_shutdown();
});
let version = self
.http_client
.get_version()
.await
.context("failed to query Polymarket CLOB protocol version")?
.version;
View on GitHub (pinned to 18893faf8b)
Solutions
- Ensure await_session_tasks fully completes (including abort) before start_generation; increase TASK_ABORT_TIMEOUT if needed
- Check the wrapped `{e}` for the task-group rejection cause
- Serialize connection attempts so a second connect cannot race the first teardown
- Restart/recreate the client if the session task group cannot accept a new generation
Example fix
// before: racing teardown and reconnect tokio::join!(adapter.disconnect(), adapter.connect()); // after: sequential lifecycle tokio::join!(adapter.disconnect()); adapter.connect().await?;
Defensive patterns
Strategy: retry
Validate before calling
// serialize lifecycle transitions let _guard = lifecycle_lock.lock().await;
Try / catch
match adapter.connect().await {
Err(e) if e.to_string().contains("session generation") => {
tokio::time::sleep(backoff).await;
adapter.connect().await?;
}
other => other?,
} Prevention
- Serialize connect/disconnect behind a lifecycle lock
- Allow the session abort timeout to fully elapse before restart
- Avoid rapid connect/disconnect cycles
When it happens
Trigger: connect_client after session_tasks was closed by begin_shutdown, when start_generation fails; await_session_tasks returned but the group has not fully released its previous generation.
Common situations: Reconnect during shutdown race; abort timeout still in flight; consecutive connect calls where the second collides with the first's teardown.
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 Betfair data session tasks: {e}
- Failed to start Betfair data command tasks: {e}
- Failed to start Polymarket task generation: {e}
- Already running
- Failed to start AX execution session generation: {e}
AI-assisted analysis of nautechsystems/nautilus_trader@18893faf8b (2026-09-08).
Data as JSON: /api/errors/b4fc766935cb0971.
Report an issue: GitHub.