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
- Read the wrapped source error (use {e:#} in logs) to see why the spawn failed.
- Do not call connect() twice on one client; instantiate a new client for a fresh connection.
- Ensure disconnect() completes before reconnecting the same client.
- 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
- One connect() per client lifecycle; rebuild on failure
- Complete disconnect() before any re-connect
- Verify runtime health before spawning clients
- Log with {e:#} to expose the wrapped spawn error
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
- IB data startup teardown failed: {teardown_error}
- task slot is already occupied
- Failed to start Hyperliquid WebSocket handler task: {e}
- Failed to connect after {max_attempts} attempts
- Unknown IB security type: {value}
AI-assisted analysis of nautechsystems/nautilus_trader@18893faf8b (2026-09-08).
Data as JSON: /api/errors/ef98fbac831ff40b.
Report an issue: GitHub.