nautechsystems/nautilus_trader · error · anyhow::Error

Failed to replay SubscribeUser: {e}

Error message

Failed to replay SubscribeUser: {e}

What it means

On reconnect, connect() replays a previously established user-channel subscription by sending HandlerCommand::SubscribeUser to the freshly spawned handler task's command channel. This error means that send failed — the new handler task's receiver was already gone, i.e. the newly started handler exited immediately (spawn failure or instant panic/error), so the user subscription could not be restored on the new session.

Source

Thrown at crates/adapters/polymarket/src/websocket/client.rs:317

            WsChannel::Market => {
                let topics = self.subscriptions.reset_after_reconnect();
                if !topics.is_empty() || self.discovery_subscribed.load(Ordering::Relaxed) {
                    log::debug!(
                        "Replaying market subscription state onto new session: assets={}, discovery={}",
                        topics.len(),
                        self.discovery_subscribed.load(Ordering::Relaxed),
                    );
                    Some((topics, connection_epoch))
                } else {
                    None
                }
            }
            WsChannel::User => {
                if self.user_subscribed.load(Ordering::Relaxed) {
                    log::debug!("Replaying user subscribe onto new session");
                    cmd_tx
                        .send(HandlerCommand::SubscribeUser)
                        .map_err(|e| anyhow::anyhow!("Failed to replay SubscribeUser: {e}"))?;
                }
                None
            }
        };

        let signal = Arc::clone(&self.signal);
        let channel = self.channel;
        let credential = self.credential.clone();
        let subscriptions = self.subscriptions.clone();
        let discovery_subscribed = Arc::clone(&self.discovery_subscribed);
        let auth_tracker = self.auth_tracker.clone();
        let user_subscribed = self.user_subscribed.load(Ordering::Relaxed);
        let subscribe_new_markets = self.subscribe_new_markets;

        if let Err(e) = self.task_handle.spawn(async move {
            let mut handler = FeedHandler::new(
                signal,
                channel,

View on GitHub (pinned to 18893faf8b)

Solutions

  1. Retry connect() after a short backoff — a transient spawn/connect failure often succeeds on the next attempt
  2. Verify auth credentials (API key/secret/passphrase) are still valid, since handler startup failures commonly stem from auth
  3. Check handler task logs/panic output for the immediate-exit cause
  4. After a successful connect(), confirm user_subscribed state matches reality and re-issue subscribe_user() if needed

Example fix

// before
client.connect().await?; // replay may fail if handler dies instantly
// after
for attempt in 0..3 {
    match client.connect().await {
        Ok(()) => break,
        Err(e) if attempt < 2 => tokio::time::sleep(Duration::from_millis(250 * (1 << attempt))).await,
        Err(e) => return Err(e),
    }
}
Defensive patterns

Strategy: retry

Validate before calling

// validate auth material before reconnect so the handler does not die at startup
if api_key.is_empty() || api_secret.is_empty() {
    return Err(anyhow::anyhow!("credentials required for user channel replay"));
}

Try / catch

match client.connect().await {
    Err(e) if e.to_string().contains("Failed to replay SubscribeUser") => {
        tokio::time::sleep(Duration::from_millis(500)).await;
        client.connect().await?; // retry: fresh handler may survive
    }
    other => other?,
}

Prevention

When it happens

Trigger: A reconnect where the just-spawned handler task dies before consuming commands — e.g. the WebSocket endpoint refuses the new connection repeatedly, the handler panics during startup, or the task is cancelled right after spawn.

Common situations: Flaky network or gateway outage during reconnect; auth credentials revoked so the handler exits on first auth attempt; calling connect() in a loop that cancels tasks faster than they can run.

Related errors


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