nautechsystems/nautilus_trader · error

Derive WebSocket event receiver not initialized

Error message

Derive WebSocket event receiver not initialized

What it means

After connecting the Derive WebSocket, `connect()` calls `take_event_receiver()` to obtain the mpsc receiver the WS client was built with. If the receiver was never initialized (or already taken), this error is thrown and a partial-connect teardown is performed.

Source

Thrown at crates/adapters/derive/src/data.rs:774

                ws_shutdown.begin_shutdown();
            });

        if !self.config.currencies.is_empty() {
            self.provider
                .load_all(None)
                .await
                .context("failed to load Derive instruments")?;
            self.cache_provider_instruments();
        }

        self.ws_client
            .connect()
            .await
            .context("failed to connect Derive WebSocket")?;
        let session_result = self
            .ws_client
            .take_event_receiver()
            .ok_or_else(|| anyhow::anyhow!("Derive WebSocket event receiver not initialized"))
            .and_then(|rx| self.spawn_stream_task(rx));

        if let Err(e) = session_result {
            if let Err(teardown_error) = self.teardown_partial_connect().await {
                return Err(e.context(format!(
                    "Derive data startup teardown failed: {teardown_error}"
                )));
            }
            return Err(e);
        }

        self.is_connected.store(true, Ordering::Release);
        setup_guard.disarm();
        log::info!(
            "Connected Derive data client ({:?})",
            self.config.environment
        );
        Ok(())

View on GitHub (pinned to 18893faf8b)

Solutions

  1. Call connect only once per data-client instance; create a new instance for reconnects.
  2. Verify the WS client construction path initializes the event receiver channel.
  3. Log the teardown error appended via `Derive data startup teardown failed` to catch secondary issues.
  4. Check for double-spawned connect tasks (actor callbacks firing twice).

Example fix

// before
client.connect().await?;
client.connect().await?; // receiver already taken
// after
client.connect().await?; // single connect per instance
// recreate client for a new session
Defensive patterns

Strategy: try-catch

Validate before calling

// Track connect-once semantics:
if already_connected { return Ok(()); } // guard before calling connect

Try / catch

match data_client.connect().await {
    Err(e) if e.to_string().contains("event receiver not initialized") => {
        // receiver consumed or missing: recreate the data client
        data_client = DeriveDataClient::new(...).await?;
        data_client.connect().await?;
    }
    other => other?,
}

Prevention

When it happens

Trigger: Calling `connect()` when `ws_client.take_event_receiver()` returns None — the WebSocket client was constructed without an event receiver, or connect is called twice so the receiver was consumed by the first call.

Common situations: Calling connect twice on the same data client; constructing the WS client through a path that skipped receiver setup; reusing a client whose first session already consumed the receiver.

Understand the failure class

Background: "This is a bug, please report it": internal invariant violations, unreachable panics, and SNH errors explained — this error's family across 47 libraries.

Related errors


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