nautechsystems/nautilus_trader · error · anyhow::Error
failed to register Polymarket message handler: {e}
Error message
failed to register Polymarket message handler: {e} What it means
Thrown when tasks.spawn(future) fails after the WS message-handler loop closure was built, meaning the task group refused to register the background task that processes incoming WebSocket messages. Without this handler, no market data would flow, so connect() fails fast.
Source
Thrown at crates/adapters/polymarket/src/data/lifecycle.rs:154
Some(msg) => handle_ws_message(msg, &ctx),
None => {
log::debug!("WebSocket message channel closed");
break;
}
}
}
() = cancellation.cancelled() => {
log::debug!("Polymarket message handler cancelled");
break;
}
}
}
log::debug!("Polymarket message handler ended");
};
self.tasks
.spawn(future)
.map_err(|e| anyhow::anyhow!("failed to register Polymarket message handler: {e}"))?;
Ok(())
}
pub(super) fn register_resolve_poll_task(&self) -> anyhow::Result<()> {
let cancellation = self.cancellation_token.clone();
let gamma_client = self.provider.http_client().clone();
let clob_public_client = self.clob_public_client.clone();
let clock = self.clock;
let resolve_poll_enabled = self.config.resolve_poll_enabled;
let subscribe_new_markets = self.config.subscribe_new_markets;
let interval_secs = self.config.resolve_poll_interval_secs.max(1);
let grace_secs = self.config.resolve_poll_grace_secs;
let max_wait_secs = self.config.resolve_poll_max_wait_secs.max(grace_secs);
let instruments = self.instruments.clone();
let token_meta = self.token_meta.clone();
let order_books = self.order_books.clone();
let last_quotes = self.last_quotes.clone();
let active_quote_subs = self.active_quote_subs.clone();View on GitHub (pinned to 18893faf8b)
Solutions
- Avoid concurrent disconnect during connect; await lifecycle calls sequentially
- Retry connect(); a new task generation is started when the group is not open
- Confirm the tokio runtime outlives the client connect call
Defensive patterns
Strategy: try-catch
Try / catch
match client.connect().await {
Err(e) if e.to_string().contains("failed to register Polymarket message handler") => {
// generation was closed; rebuild or retry
client = build_client(cfg)?;
client.connect().await?;
}
r => r?,
} Prevention
- One owner task should drive connect/disconnect (single lifecycle actor)
- Do not drop the runtime while connect() futures are in flight
- Treat any 'failed to register ...' error as a generation failure and retry from a clean state
When it happens
Trigger: tasks.spawn() returns Err during register_message_handler — typically because the task group is closed (shutdown started) or the runtime is terminating between obtaining the spawner and spawning the task.
Common situations: Disconnect racing connect; runtime dropped mid-connect; task group admission window closed by an earlier failed registration in the same connect sequence.
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 finish Binance Futures data command tasks: {e}
- Failed to start Coinbase WebSocket handler task: {e}
- Failed to start Hyperliquid WebSocket handler task: {e}
- Failed to start Polymarket WebSocket handler task: {e}
- Failed to register Betfair keep-alive task: {e}
AI-assisted analysis of nautechsystems/nautilus_trader@18893faf8b (2026-09-08).
Data as JSON: /api/errors/595b3cb627f7a4e6.
Report an issue: GitHub.