nautechsystems/nautilus_trader · error · anyhow::Error

Polymarket session task admission is closed: {e}

Error message

Polymarket session task admission is closed: {e}

What it means

Before spawning the WebSocket dispatch task, `start_ws_stream` acquires a spawner from the `session_tasks` task group. If the task group's admission is closed (shutdown has begun), `spawner()` fails and this error is returned. It means the adapter is shutting down or not yet restarted for a new generation, so no new session tasks can be admitted.

Source

Thrown at crates/adapters/polymarket/src/execution/lifecycle.rs:319

        let http_client = self.http_client.clone();
        let clock = self.clock;
        let signature_type = self.config.signature_type;
        let stopping = self.stopping.clone();
        let user_address = self
            .secrets
            .funder
            .clone()
            .unwrap_or_else(|| self.secrets.address.clone());
        let user_api_key = SecretString::from(self.secrets.credential.api_key_str().to_string());

        let fill_tracker = self.fill_tracker.clone();
        let pending_submits = self.pending_submits.clone();
        let order_contexts = self.order_contexts.clone();
        let ws_dispatch_state = self.ws_dispatch_state.clone();
        let session_spawner = self
            .session_tasks
            .spawner()
            .map_err(|e| anyhow::anyhow!("Polymarket session task admission is closed: {e}"))?;

        if let Err(e) = self.session_tasks.spawn(async move {
            let ctx = WsDispatchContext {
                token_instruments: &token_instruments,
                fill_tracker: &fill_tracker,
                pending_submits: &pending_submits,
                order_contexts: &order_contexts,
                emitter: &emitter,
                account_id,
                clock,
                user_address: &user_address,
                user_api_key: user_api_key.expose_secret(),
            };

            loop {
                match rx.recv().await {
                    Some(PolymarketWsMessage::User(user_msg)) => {
                        let refresh = {

View on GitHub (pinned to 18893faf8b)

Solutions

  1. Do not call connect while the client is stopping; check the stopping flag/state before connecting
  2. Ensure connect_client's start_generation path runs (reopening admission) before spawning session tasks
  3. Serialize connect/disconnect calls behind a lock or the existing setup_guard
  4. Retry connect after the shutdown generation has fully finished

Example fix

// before: connecting during shutdown
if stopping { return; }
adapter.connect().await?;
// after: guard against closed admission with proper lifecycle ordering
if adapter.is_stopping() {
    return; // refuse connect during teardown
}
adapter.connect().await?;
Defensive patterns

Strategy: try-catch

Validate before calling

// refuse connect while adapter is stopping
if adapter.is_stopping() { return Err(anyhow!("cannot connect during shutdown")); }

Try / catch

match adapter.connect().await {
    Err(e) if e.to_string().contains("admission is closed") => {
        // wait for shutdown generation to finish, then retry
        tokio::time::sleep(Duration::from_secs(1)).await;
    }
    other => other?,
}

Prevention

When it happens

Trigger: Calling connect_client after await_session_tasks/begin_shutdown has closed session-task admission and before start_generation reopens it; a racing teardown closing the group while connect is in progress.

Common situations: Concurrent connect and disconnect calls on the execution client; reconnect attempt issued during adapter shutdown; stop flag set while a connect is still completing.

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/8b7aee3652ec4a03. Report an issue: GitHub.