nautechsystems/nautilus_trader · error
RPC block feed active without an RPC client
Error message
RPC block feed active without an RPC client
What it means
unsubscribe_block_feed sees an active RPC block feed backend but the core client's rpc_client is None, which is an inconsistent state — a live RPC subscription exists without the client that owns it. It bails rather than silently skipping cleanup.
Source
Thrown at crates/adapters/blockchain/src/data/client.rs:1103
core_client
.subscription_manager
.block_feed_started(started_backend);
Ok(())
}
async fn unsubscribe_block_feed(
core_client: &mut BlockchainDataClientCore,
owner: BlockFeedOwner,
) -> anyhow::Result<()> {
let Some(backend) = core_client.subscription_manager.remove_block_demand(owner) else {
log::debug!("Keeping block subscription active while another owner remains");
return Ok(());
};
match backend {
BlockFeedBackend::Rpc => {
let Some(rpc) = core_client.rpc_client.as_mut() else {
anyhow::bail!("RPC block feed active without an RPC client")
};
rpc.unsubscribe_blocks().await?;
log::debug!("Unsubscribed from blocks via RPC");
}
BlockFeedBackend::HyperSync => {
core_client.hypersync_client.unsubscribe_blocks().await;
log::debug!("Unsubscribed from blocks via HyperSync");
}
}
core_client.subscription_manager.block_feed_stopped(backend);
Ok(())
}
/// Processes DeFi request commands to fetch specific blockchain data.
async fn handle_request_command(
command: DefiRequestCommand,
core_client: &mut BlockchainDataClientCore,View on GitHub (pinned to 18893faf8b)
Solutions
- Ensure the same client instance/config that subscribed (with rpc_client present) performs the unsubscribe
- Re-initialize the RPC client before unsubscribing
- If switching backends intentionally, unsubscribe with the correct backend selection
Example fix
// before
// client recreated without rpc url; unsubscribe_block_feed() fails
// after
client.reconnect_with_rpc("wss://...")?; // restores rpc_client
client.unsubscribe_block_feed().await?; Defensive patterns
Strategy: type-guard
Validate before calling
if backend == BlockFeedBackend::Rpc && client.rpc_client().is_none() {
log::warn!("rpc client gone; skipping rpc block unsubscribe");
return;
} Type guard
fn rpc_available(c: &BlockchainDataClient) -> bool { c.core.rpc_client.is_some() } Try / catch
match client.unsubscribe_block_feed().await {
Err(e) if e.to_string().contains("active without an RPC client") => {
log::warn!("stale rpc backend state; resetting block feed state");
}
r => r?,
} Prevention
- Keep backend state and rpc_client lifecycle in sync (reset backend when rpc_client drops)
- Rebuild the client fully rather than partially on reconnect
- Log backend transitions to catch divergence early
When it happens
Trigger: Calling unsubscribe_block_feed when the tracked backend is BlockFeedBackend::Rpc but the client was rebuilt/reconnected without rpc_client, or the backend record was set to Rpc while rpc_client was dropped.
Common situations: Client re-initialization between subscribe and unsubscribe; mixing backend configurations across reconnects; internal state corruption after an RPC client teardown.
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
- RPC block feed selected without an RPC client
- Finalized block {} does not contain transaction {}
- Included wrap transaction {tx_hash} has invalid block number
- WETH balance overflow for included transaction {tx_hash} at
- Finalized execution transaction {tx_hash} no longer has a re
AI-assisted analysis of nautechsystems/nautilus_trader@18893faf8b (2026-09-08).
Data as JSON: /api/errors/b1487a8a3bfa4d1e.
Report an issue: GitHub.