nautechsystems/nautilus_trader · error

failed to register IB data farm monitor

Error message

failed to register IB data farm monitor

What it means

InteractiveBrokersDataClient::connect reaches the point of spawning the IB data farm notice monitor task; if the spawn into session_tasks fails, the client rolls back (shuts down task groups, clears ib_client) and returns the original spawn error wrapped as 'failed to register IB data farm monitor'.

Source

Thrown at crates/adapters/interactive_brokers/src/data/core.rs:752

        let cancellation_token = self.cancellation_token.child_token();
        let clock = self.clock;

        if let Err(e) = self.session_tasks.spawn(async move {
            if let Err(e) =
                monitor_data_farm_notices(client, data_farm_state, clock, cancellation_token).await
            {
                tracing::warn!("IB data farm notice monitor stopped: {e:?}");
            }
        }) {
            self.session_tasks.begin_shutdown();
            self.command_tasks.begin_shutdown();
            self.ib_client = None;

            if let Err(teardown_error) = self.finish_tasks().await {
                return Err(anyhow::Error::new(e)
                    .context(format!("IB data startup teardown failed: {teardown_error}")));
            }
            return Err(anyhow::Error::new(e).context("failed to register IB data farm monitor"));
        }
        self.is_connected.store(true, Ordering::Relaxed);

        let instrument_count = self.instrument_provider.count();
        if instrument_count > 0 {
            tracing::debug!(
                "Data client connected with {} instruments in provider cache",
                instrument_count
            );

            for instrument in self.instrument_provider.get_all() {
                if let Err(e) = self.data_sender.send(DataEvent::Instrument(instrument)) {
                    tracing::warn!("Failed to publish startup-loaded instrument: {e}");
                    break;
                }
            }
        }

View on GitHub (pinned to 18893faf8b)

Solutions

  1. Read the wrapped source error (use {e:#} in logs) to see why the spawn failed.
  2. Do not call connect() twice on one client; instantiate a new client for a fresh connection.
  3. Ensure disconnect() completes before reconnecting the same client.
  4. Confirm the tokio runtime is active (not in shutdown) for the duration of connect().

Example fix

// before
client.connect().await?; // ... later
client.connect().await?; // Err: failed to register IB data farm monitor
// after
client.disconnect().await?; client.connect().await?; // or build a new client
Defensive patterns

Strategy: try-catch

Validate before calling

// ensure task groups are not already shut down before connect
if client.is_connected() { return Ok(()); }

Type guard

fn can_connect(client: &IBDataClient) -> bool { !client.is_connected() }

Try / catch

match client.connect().await {
    Err(e) if format!("{e:#}").contains("failed to register IB data farm monitor") => {
        // task group poisoned; create a new client instead of retrying on this one
    }
    r => r?,
}

Prevention

When it happens

Trigger: connect() to IB Gateway/TWS succeeds, then session_tasks.spawn() of monitor_data_farm_notices returns Err — typically because the task group is already shut down or the async runtime cannot spawn new tasks.

Common situations: Double-connect on the same client instance, connecting after a prior disconnect, or running inside a runtime that is shutting down; also seen when a previous connect failure left the task group poisoned.

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