nautechsystems/nautilus_trader · error
Failed to read the consensus finalized block; the execution
Error message
Failed to read the consensus finalized block; the execution endpoint must support the finalized tag: {e} What it means
`finalized_block()` calls `block_by_tag("finalized", ...)`, which requires the execution endpoint to support the post-merge `finalized` block tag via `eth_getBlockByNumber`. When the underlying call fails for any reason (unsupported tag, RPC failure, malformed result), the error is re-wrapped with this message telling the operator the endpoint must support the finalized tag.
Source
Thrown at crates/adapters/blockchain/src/rpc/http.rs:656
/// Returns the latest block via `eth_getBlockByNumber` with the `latest` tag.
///
/// # Errors
///
/// Returns an error if the RPC call fails or the result is missing or malformed.
pub async fn latest_block(&self) -> anyhow::Result<RpcBlock> {
self.block_by_tag("latest", false).await
}
/// Returns the consensus finalized block.
///
/// # Errors
///
/// Returns an error if the endpoint does not support the `finalized` tag, the RPC call
/// fails, or the result is missing or malformed.
pub async fn finalized_block(&self) -> anyhow::Result<RpcBlock> {
self.block_by_tag("finalized", false).await.map_err(|e| {
anyhow::anyhow!(
"Failed to read the consensus finalized block; the execution endpoint must support the finalized tag: {e}"
)
})
}
/// Returns a numbered canonical block, optionally with full transactions.
///
/// # Errors
///
/// Returns an error if the RPC call fails or the result is missing or malformed.
pub async fn block_by_number(
&self,
number: u64,
full_transactions: bool,
) -> anyhow::Result<RpcBlock> {
let block = self
.block_by_tag(&format!("0x{number:x}"), full_transactions)
.await?;View on GitHub (pinned to 18893faf8b)
Solutions
- Upgrade the execution client to a post-merge version supporting the `finalized` tag (geth >= v1.10.x era, reth, etc.)
- Ensure the execution node is connected to a consensus client (beacon node) so finalized blocks are known
- Check the inner error text (appended after the colon) for the root cause: unsupported tag vs RPC failure vs null result
- If the provider does not support `finalized`, use `safe` or `latest` tags where the fork-verification config allows
Example fix
// before: old execution node without finalized tag support
// geth v1.9.x -> upgrade
// after
// geth version >= 1.13 with a connected beacon node
// curl -X POST $RPC -d '{"jsonrpc":"2.0","method":"eth_getBlockByNumber","params":["finalized",false],"id":1}' Defensive patterns
Strategy: fallback
Validate before calling
async fn supports_finalized_tag(url: &str) -> bool {
send_raw(url, json!({"jsonrpc":"2.0","method":"eth_getBlockByNumber","params":["finalized",false],"id":1}))
.await.ok()
.and_then(|v| v.get("result").cloned())
.map(|r| !r.is_null())
.unwrap_or(false)
} Try / catch
let block = match client.finalized_block().await {
Ok(b) => b,
Err(e) if e.to_string().contains("finalized") => {
log::warn!("endpoint lacks finalized tag; falling back to safe/latest");
client.latest_block().await?
}
Err(e) => return Err(e),
}; Prevention
- Run a post-merge execution client with a connected consensus client
- Verify `eth_getBlockByNumber ["finalized",false]` returns a block during setup
- Check provider documentation that the tier supports post-merge block tags
- Read the inner error appended after the colon to distinguish tag-unsupported from RPC failure
When it happens
Trigger: Calling `finalized_block()` against an execution node that does not implement the `finalized` tag (pre-merge clients, some third-party providers, or a consensus/execution mispair), or the underlying eth_getBlockByNumber call fails or returns null.
Common situations: Running an old geth/erigon version predating finalized-tag support; provider tier that excludes post-merge tags; execution endpoint not wired to a consensus client so no finalized head exists.
Understand the failure class
Background: UnsupportedOperationException and "is not supported" errors: when a library deliberately refuses a call — this error's family across 30 libraries.
Related errors
- Included wrap transaction {tx_hash} has invalid block number
- RPC error {}: {}
- {method} RPC error {code}
- {method} RPC error {}
- eth_getBlockByNumber returned block {} for requested block {
AI-assisted analysis of nautechsystems/nautilus_trader@18893faf8b (2026-09-08).
Data as JSON: /api/errors/0b36bedc69eb3758.
Report an issue: GitHub.