nautechsystems/nautilus_trader · error · anyhow::Error
Failed to send AddBarType command: {e}
Error message
Failed to send AddBarType command: {e} What it means
This error wraps a failed send of AddBarType on the internal mpsc command channel during bar subscription. After registering the instrument, the client sends the BarType key to the handler so incoming bar data is routed; failure means the handler task's receiver is closed. The client rolls back its local bar_types registry before returning this error.
Source
Thrown at crates/adapters/hyperliquid/src/websocket/client.rs:1602
let interval = bar_type_to_interval(&bar_type)?;
let subscription = SubscriptionRequest::Candle { coin, interval };
// Cache the bar type for parsing using canonical key
let key = format!("candle:{coin}:{interval}");
self.bar_types.insert(key.clone(), bar_type);
let cmd_tx = self.cmd_tx.read().await;
cmd_tx
.send(HandlerCommand::UpdateInstrument(instrument.clone()))
.map_err(|e| anyhow::anyhow!("Failed to send UpdateInstrument command: {e}"))?;
cmd_tx
.send(HandlerCommand::AddBarType {
key: key.clone(),
bar_type,
})
.map_err(|e| anyhow::anyhow!("Failed to send AddBarType command: {e}"))?;
if let Err(e) = self.send_subscription(&cmd_tx, subscription) {
self.bar_types.remove(&key);
let _ = cmd_tx.send(HandlerCommand::RemoveBarType { key });
return Err(e);
}
Ok(())
}
/// Subscribe to funding rate updates for an instrument.
pub async fn subscribe_funding_rates(&self, instrument_id: InstrumentId) -> anyhow::Result<()> {
self.subscribe_asset_context_data(instrument_id, AssetContextDataType::FundingRate)
.await
}
/// Subscribe to open interest updates for an instrument.
pub async fn subscribe_open_interest(&self, instrument_id: InstrumentId) -> anyhow::Result<()> {
self.subscribe_asset_context_data(instrument_id, AssetContextDataType::OpenInterest)View on GitHub (pinned to 18893faf8b)
Solutions
- Verify the handler task is alive before subscribing; respawn/reconnect the client if not.
- Do not call subscribe_bars concurrently with disconnect/shutdown.
- If the handler loop exited, create a fresh client; the channel cannot be reopened.
- Check handler-task logs for the root cause of the exit.
Example fix
// before client.disconnect().await?; client.subscribe_bars(bar_type).await?; // channel closed // after client.subscribe_bars(bar_type).await?; client.disconnect().await?;
Defensive patterns
Strategy: try-catch
Validate before calling
// rust
if !client.is_connected() {
return Err(anyhow::anyhow!("cannot subscribe bars: handler channel closed"));
} Try / catch
// rust
if let Err(e) = client.subscribe_bars(bar_type).await {
if e.to_string().contains("AddBarType") {
tracing::warn!("bar subscribe lost handler ({e}); reconnecting");
client = reconnect_client().await?;
client.subscribe_bars(bar_type).await?;
} else { return Err(e); }
} Prevention
- Sequence bar subscribe before any disconnect call.
- Keep the handler task alive for the whole session, not per-request.
- Watch for handler-task panics via panic hooks/logging.
- After a closed-channel error, discard the client and build a fresh one.
When it happens
Trigger: Calling subscribe_bars when the handler task has exited between the UpdateInstrument send and the AddBarType send, or already before — after disconnect(), handler panic, or task cancellation.
Common situations: Shutdown racing a bar subscribe; handler task aborted via its JoinHandle; stale client instance reused post-teardown; handler panic on prior traffic.
Related errors
- Failed to send SetDepth10Sub command: {e}
- Failed to send UpdateTradeSubs command: {e}
- Failed to send resubscribe command: {e}
- Failed to send RemoveBarType command: {e}
- Failed to send subscribe command: {e}
AI-assisted analysis of nautechsystems/nautilus_trader@18893faf8b (2026-09-08).
Data as JSON: /api/errors/31eaec150cc0dea7.
Report an issue: GitHub.