nautechsystems/nautilus_trader · error · anyhow::Error
Failed to send resubscribe command: {e}
Error message
Failed to send resubscribe command: {e} What it means
This error wraps a failed send of HandlerCommand::Resubscribe on the internal mpsc command channel, used when re-establishing an existing subscription (e.g. after changing stream options). It fails only when the handler task's receiver is closed, meaning the handler loop is not running. Without the handler, the resubscribe request cannot reach the WebSocket connection.
Source
Thrown at crates/adapters/hyperliquid/src/websocket/client.rs:1864
// Keep the registration check atomic with the resubscribe pair
let cmd_tx = self.cmd_tx.write().await;
if !self.quote_streams.contains_key(&coin) {
log::debug!("Skipping bbo resubscribe for {coin}: stream no longer registered");
return Ok(());
}
self.send_stream_resubscribe(&cmd_tx, SubscriptionRequest::Bbo { coin })
}
fn send_stream_resubscribe(
&self,
cmd_tx: &tokio::sync::mpsc::UnboundedSender<HandlerCommand>,
subscription: SubscriptionRequest,
) -> anyhow::Result<()> {
cmd_tx
.send(HandlerCommand::Resubscribe { subscription })
.map_err(|e| anyhow::anyhow!("Failed to send resubscribe command: {e}"))
}
/// Unsubscribe from trades for an instrument.
pub async fn unsubscribe_trades(&self, instrument_id: InstrumentId) -> anyhow::Result<()> {
self.unsubscribe_trade_stream(instrument_id, TradeStreamUse::Ticks)
.await
}
/// Unsubscribe from complete public trades for an instrument.
pub async fn unsubscribe_public_trades(
&self,
instrument_id: InstrumentId,
) -> anyhow::Result<()> {
self.unsubscribe_trade_stream(instrument_id, TradeStreamUse::PublicTrades)
.await
}
async fn unsubscribe_trade_stream(View on GitHub (pinned to 18893faf8b)
Solutions
- Confirm the handler task is running before resubscribing; reconnect and resubscribe on a fresh client if it exited.
- Treat this during teardown as benign and skip the resubscribe.
- Serialize resubscribe calls with disconnect/shutdown to avoid races.
- Check handler logs for a panic that ended the loop.
Example fix
// before client.disconnect().await?; client.subscribe_book_depth10_with_options(id, Some(2), None).await?; // resubscribe path, channel closed // after client.connect().await?; // ensure handler is running client.subscribe_book_depth10_with_options(id, Some(2), None).await?;
Defensive patterns
Strategy: try-catch
Validate before calling
// rust
if !client.is_connected() {
return Err(anyhow::anyhow!("cannot resubscribe: client disconnected"));
} Try / catch
// rust
if let Err(e) = client.subscribe_book_depth10_with_options(id, Some(2), None).await {
if e.to_string().contains("resubscribe") {
client = reconnect_client().await?;
client.subscribe_book_depth10_with_options(id, Some(2), None).await?;
} else { return Err(e); }
} Prevention
- Only resubscribe on a client with a live handler task.
- Skip resubscribes during shutdown once a disconnect has begun.
- Serialize option-change resubscribes with connection lifecycle changes.
- Investigate handler logs when resubscribe sends fail; something ended the loop.
When it happens
Trigger: Calling a resubscribe-capable API (e.g. subscribe_book_depth10_with_options on an active stream with different options, routed through send_resubscribe) after disconnect() or handler-task exit.
Common situations: Re-subscribing after a reconnect attempt that left the handler dead; changing depth-10 options on a client whose handler already stopped; shutdown racing a resubscribe.
Related errors
- Failed to send SetDepth10Sub command: {e}
- Failed to send UpdateTradeSubs command: {e}
- Failed to send AddBarType 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/e3555dafc4d8f803.
Report an issue: GitHub.