nautechsystems/nautilus_trader · error · anyhow::Error

failed to register Polymarket instrument refresh: {e}

Error message

failed to register Polymarket instrument refresh: {e}

What it means

Thrown by register_instrument_refresh_task when self.tasks.spawn(future) fails, meaning the Polymarket data client's task group refused to admit the periodic instrument-refresh background task. This typically happens because the task group is closed/shutting down (post-disconnect) or the spawner could not accept a new task. connect() then propagates this as the data-client connection error.

Source

Thrown at crates/adapters/polymarket/src/data/instruments.rs:595

                {
                    Ok(total) => {
                        if total > 0 {
                            log::debug!(
                                "Refreshed {total} Polymarket instruments into the live cache"
                            );
                        }
                    }
                    Err(e) => {
                        log::error!("Failed to refresh Polymarket instruments: {e}");
                    }
                }
            }

            log::debug!("Polymarket instrument refresh task ended");
        };

        self.tasks.spawn(future).map_err(|e| {
            anyhow::anyhow!("failed to register Polymarket instrument refresh: {e}")
        })?;
        Ok(())
    }
}

#[cfg(test)]
mod tests {
    use std::{
        net::SocketAddr,
        sync::atomic::{AtomicUsize, Ordering},
    };

    use axum::{
        Json, Router,
        extract::{RawQuery, State},
        http::StatusCode,
        response::{IntoResponse, Response},
        routing::get,

View on GitHub (pinned to 18893faf8b)

Solutions

  1. Ensure disconnect()/cancel is not racing connect(): await or drop the disconnect before calling connect
  2. Do not call connect() during application shutdown; check client state first
  3. Verify the tokio runtime is alive for the duration of connect()
  4. Retry the connect() on a fresh client instance; the task generation is restarted on next connect

Example fix

// before: racing calls
client.connect();
client.disconnect();
// after: sequential lifecycle
client.disconnect().await?;
client.connect().await?;
Defensive patterns

Strategy: try-catch

Validate before calling

// Rust: check lifecycle state before connecting
assert!(!is_disconnecting(&client), "client is shutting down; do not connect");

Type guard

fn is_connectable(client: &PolymarketDataClient) -> bool { !client.is_disconnecting() && runtime_is_alive() }

Try / catch

match client.connect().await {
    Err(e) if e.to_string().contains("failed to register Polymarket instrument refresh") => {
        log::warn!("connect raced shutdown; retrying");
        client.connect().await?;
    }
    r => r?,
}

Prevention

When it happens

Trigger: Calling connect()/connect_client while the client's TaskGroup is shutting down or already closed, so tasks.spawn() rejects the instrument refresh future; also any internal spawn error (e.g. runtime shutdown in progress).

Common situations: Concurrent disconnect() racing with connect(); reconnect attempt issued after cancellation was initiated; app shutdown triggering disconnect while a connect is still completing; dropping the tokio runtime while client connect is in flight.

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


AI-assisted analysis of nautechsystems/nautilus_trader@18893faf8b (2026-09-08). Data as JSON: /api/errors/c7aab31d739cf48c. Report an issue: GitHub.