linera-io/linera-protocol · error

failed to check block finality — block may not exist

Error message

failed to check block finality — block may not exist

What it means

is_block_hash_finalized in the service calls ServiceEthereumClient::is_block_hash_finalized against the configured RPC endpoint and expects success. The panic means the RPC interaction failed — endpoint unreachable, rate-limited, erroring, or the block genuinely not found/not yet finalized — and it propagates as a GraphQL error to the contract's VerifyBlockHash oracle, which then also aborts. This is the service-side twin of the contract's finality check.

Source

Thrown at linera-bridge/contracts/evm-bridge/src/service.rs:224

    ///
    /// Makes the EVM JSON-RPC calls in the service runtime so that the contract
    /// sees a single deterministic oracle response (the boolean result) instead
    /// of multiple raw HTTP responses with non-deterministic headers.
    async fn is_block_hash_finalized(&self, block_hash: String) -> bool {
        let bytes: [u8; 32] = hex::decode(block_hash.strip_prefix("0x").unwrap_or(&block_hash))
            .expect("invalid hex")
            .try_into()
            .expect("hash must be 32 bytes");
        let rpc_endpoint = self.state.rpc_endpoint.get().clone();
        assert!(
            !rpc_endpoint.is_empty(),
            "rpc_endpoint must be configured to verify block hashes"
        );
        let client = ServiceEthereumClient::new(rpc_endpoint);
        client
            .is_block_hash_finalized(B256::from(bytes))
            .await
            .expect("failed to check block finality — block may not exist")
    }
}

View on GitHub (pinned to 6c226ddcb3)

Solutions

  1. Check provider health first: a simple eth_blockNumber call to the same endpoint
  2. If the block is recent, wait for finality (2 epochs on Ethereum PoS) and retry VerifyBlockHash
  3. Verify the endpoint still reports the bridge's source_chain_id (chain mismatch makes blocks 'not exist')
  4. For production, use a redundant/paid RPC tier or a local node to avoid rate limits
  5. Treat repeated failures as an operations incident: deposits depending on the oracle will stall

Example fix

# before
linera query-service ... 'query { isBlockHashFinalized(blockHash: "0x...") }'
# -> error: failed to check block finality — block may not exist

# after — triage then retry
curl -s $RPC -X POST -H 'content-type: application/json' \
  -d '{"jsonrpc":"2.0","method":"eth_getBlockByHash","params":["0x...",false],"id":1}'
# null result -> wrong network/pruned/not known yet: fix endpoint or wait for finality
# block present -> transient RPC fault: retry the query
Defensive patterns

Strategy: retry

Validate before calling

// Triage before retrying the finality query:
async fn rpc_alive(url: &str) -> bool {
    reqwest::Client::new().post(url).json(&serde_json::json!({
        "jsonrpc": "2.0", "method": "eth_blockNumber", "params": [], "id": 1
    })).send().await.map(|r| r.status().is_success()).unwrap_or(false)
}

Try / catch

// Retry with backoff at the caller; the service query itself either returns
// true/false or errors:
for attempt in 0..4 {
    match query_finality(&block_hash).await {
        Ok(v) => return Ok(v),
        Err(_) if attempt < 3 => tokio::time::sleep(Duration::from_secs(2u64 << attempt))).await,
        Err(e) => return Err(e),
    }
}

Prevention

When it happens

Trigger: Calling VerifyBlockHash while the rpc_endpoint is down or rate-limiting; querying a block hash that does not exist on the endpoint (wrong network, pruned, or not yet known); transient network partitions between validators and the RPC provider; provider returning 429/5xx during load spikes.

Common situations: RPC provider incidents or quota exhaustion during high bridge traffic; querying finality of very recent blocks the provider has not indexed; misconfigured endpoint pointing at a different network than the block belongs to.

Related errors


AI-assisted analysis of linera-io/linera-protocol@6c226ddcb3 (2026-08-22). Data as JSON: /api/errors/ee5218c313ab1be3. Report an issue: GitHub.