nautechsystems/nautilus_trader · error · anyhow::Error
Polymarket WebSocket startup rollback failed: {shutdown_erro
Error message
Polymarket WebSocket startup rollback failed: {shutdown_error} What it means
During Polymarket WebSocket startup (start_ws_stream, invoked from connect_client), if the spawned user-stream handler task fails immediately, the client attempts a rollback via ws_client.disconnect(). If that rollback disconnect ALSO fails, the original error is re-wrapped with "Polymarket WebSocket startup rollback failed: {shutdown_error}" so both failures are visible. It signals a broken WebSocket lifecycle where neither start nor clean teardown succeeded.
Source
Thrown at crates/adapters/polymarket/src/execution/lifecycle.rs:404
}
}
};
if let Err(e) = session_spawner.spawn(future) {
log::debug!("Skipping reconnect refresh during shutdown: {e}");
}
}
None => {
log::debug!("User WebSocket stream ended");
break;
}
}
}
log::debug!("User WebSocket handler task completed");
}) {
if let Err(shutdown_error) = self.ws_client.disconnect().await {
return Err(anyhow::Error::new(e).context(format!(
"Polymarket WebSocket startup rollback failed: {shutdown_error}"
)));
}
return Err(e.into());
}
Ok(())
}
async fn teardown_partial_connect(&mut self) -> anyhow::Result<()> {
self.stopping.store(true, Ordering::Release);
self.clear_order_event_subscription();
self.clear_position_event_subscription();
self.abort_session_tasks();
self.abort_pending_tasks();
self.ws_client.begin_shutdown();
if let Err(e) = self.ws_client.disconnect().await {View on GitHub (pinned to 18893faf8b)
Solutions
- Fix the ORIGINAL startup error (first error in the anyhow chain) — the rollback message is secondary.
- Check Polymarket WS credentials and endpoint URL configuration.
- Verify network reachability of the Polymarket WebSocket host.
- Ensure the client is fully dropped/recreated rather than reused after a failed connect.
- Add backoff between reconnect attempts so state can settle before reconnecting.
Defensive patterns
Strategy: fallback
Validate before calling
// validate WS config before connect
assert!(!ws_url.is_empty() && ws_url.starts_with("wss://"), "valid WS URL");
assert!(credentials_present(), "API credentials configured"); Try / catch
match client.connect().await {
Ok(()) => {}
Err(e) => {
error!("connect failed (incl. rollback): {e:#}");
drop(client); // discard possibly-corrupt client state
let mut fresh = new_client(config)?;
backoff_retry(|| fresh.connect()).await?;
}
} Prevention
- Fix the original startup error first; the rollback message is secondary
- Recreate the client after a failed connect instead of reusing it
- Validate WS URL and credentials before connecting
- Use exponential backoff between reconnect attempts
When it happens
Trigger: Calling connect on a Polymarket execution/data client where the user WebSocket handler task errors during startup (auth failure, bad URL, network error) and the subsequent disconnect() call also errors (e.g. socket already broken, internal state inconsistent).
Common situations: Invalid or missing Polymarket WebSocket credentials; unreachable host / DNS failure during startup; calling connect while a previous connection is half-torn-down; aggressive reconnect loops compounding state corruption.
Understand the failure class
Background: ECONNREFUSED and "connection refused" / "could not connect to server" errors: what they mean and how to fix them — this error's family across 44 libraries.
Related errors
- {e}; subscription rollback failed: {close_error}
- Failed to start market shard forwarder: {e}; startup rollbac
- Failed to start market shard forwarder: {e}
- std::mem::take(&mut self.shutdown_errors).join("; ")
- Failed to start Spot public JSON WS bytes task: {e}
AI-assisted analysis of nautechsystems/nautilus_trader@18893faf8b (2026-09-08).
Data as JSON: /api/errors/115ffc620555b6d4.
Report an issue: GitHub.