nautechsystems/nautilus_trader · error · anyhow::Error

Architect AX data WebSocket handler failed: {error}

Error message

Architect AX data WebSocket handler failed: {error}

What it means

Returned by the Architect AX data WebSocket client's close(). After aborting, it joins the handler task and maps the outcome: if the handler task ended in an error (TaskJoinOutcome::Failed), close() propagates that error wrapped in this anyhow message instead of returning Ok.

Source

Thrown at crates/adapters/architect_ax/src/websocket/data/client.rs:1078

        self.cancellation_token.load().cancel();
        let _ = self.send_cmd(HandlerCommand::Disconnect).await;
        tokio::time::sleep(Duration::from_millis(50)).await;
        self.signal.store(true, Ordering::Release);

        let outcome = self
            .task_handle
            .finish(Duration::from_secs(2), Duration::from_secs(2))
            .await;

        *self.reconnect_headers.lock() = None;

        if let Some(control) = &self.socket_control {
            control.deregister();
        }

        match outcome {
            None | Some(TaskJoinOutcome::Completed(()) | TaskJoinOutcome::Aborted) => Ok(()),
            Some(TaskJoinOutcome::Failed(error)) => Err(anyhow::anyhow!(
                "Architect AX data WebSocket handler failed: {error}"
            )),
            Some(TaskJoinOutcome::Incomplete) => Err(anyhow::anyhow!(
                "Architect AX data WebSocket handler did not stop after abort"
            )),
        }
    }

    async fn send_cmd(&self, cmd: HandlerCommand) -> AxWsResult<()> {
        let guard = self.cmd_tx.read().await;
        guard
            .send(cmd)
            .map_err(|e| AxWsClientError::ChannelError(e.to_string()))
    }
}

impl Drop for AxMdWebSocketClient {
    fn drop(&mut self) {

View on GitHub (pinned to 18893faf8b)

Solutions

  1. Inspect the inner handler error (the {error} payload) to find the root cause before looking at close() itself
  2. Check server/connectivity logs around shutdown time for why the handler task failed
  3. Ensure close() is only called during teardown and handle the returned Err as a non-fatal shutdown warning if the session is ending anyway
  4. Update the adapter if the root cause is a handler bug on specific message types

Example fix

// before
client.close().await?; // may fail with handler error
// after
if let Err(e) = client.close().await {
    tracing::warn!("data ws close: {e:#}"); // handler already failed; teardown continues
}
Defensive patterns

Strategy: try-catch

Try / catch

// Rust
match client.close().await {
    Ok(()) => {},
    Err(e) => tracing::warn!("data ws handler failed on close: {e:#}"),
}

Prevention

When it happens

Trigger: Calling DataWebSocketClient::close() while the internal data handler task has terminated with an error — e.g. the handler failed on a malformed inbound frame, a send-channel error, or an unexpected stream termination rather than completing or being aborted cleanly.

Common situations: The remote feed dropped the connection mid-session with a handler-level error; a code bug in the message handler caused a panic/result error; shutdown raced with an already-failed handler in tests or teardown.

Related errors


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