FuelLabs/fuel-core · error · anyhow::Error

Failed to fetch latest block height: {err}

Error message

Failed to fetch latest block height: {err}

What it means

`Importer::latest_block_height` queries the Tendermint RPC endpoint (`abci_info` JSON-RPC call via `http_api::latest_block_height`) and wraps any failure with the context "Failed to fetch latest block height". The inner `err` is either a reqwest network error, a non-success RPC response, or a parse error of `last_block_height`. It indicates the shared sequencer could not read the current Celestia/Tendermint chain height.

Source

Thrown at crates/services/shared-sequencer/src/lib.rs:125

            http,
        })
    }

    /// Returns the Cosmos account ID of the sender.
    pub fn sender_account_id<S: Signer>(&self, signer: &S) -> anyhow::Result<AccountId> {
        let sender_public_key = signer.public_key();
        let sender_account_id = sender_public_key
            .account_id(&self.account_prefix)
            .map_err(|err| anyhow!("{err:?}"))?;

        Ok(sender_account_id)
    }

    /// Retrieve latest block height
    pub async fn latest_block_height(&self) -> anyhow::Result<u32> {
        http_api::latest_block_height(&self.http, &self.endpoints.tendermint_rpc_api)
            .await
            .map_err(|err| anyhow!("Failed to fetch latest block height: {err}"))
    }

    /// Retrieve account metadata by its ID
    pub async fn get_account_meta<S: Signer>(
        &self,
        signer: &S,
    ) -> anyhow::Result<AccountMetadata> {
        let sender_account_id = self.sender_account_id(signer)?;
        http_api::get_account(
            &self.http,
            &self.endpoints.blockchain_rest_api,
            sender_account_id,
        )
        .await
    }

    /// Retrieve the topic info, if it exists
    pub async fn get_topic(&self) -> anyhow::Result<Option<TopicInfo>> {

View on GitHub (pinned to add100d30d)

Solutions

  1. Verify the `tendermint_rpc_api` endpoint URL and that the Tendermint/Celestia node is reachable: `curl <url> -X POST -d '{"jsonrpc":"2.0","method":"abci_info","id":1}'`.
  2. Fix network-level issues: correct host/port, firewall rules, and ensure the sequencer node is fully synced and serving RPC.
  3. Increase HTTP timeouts or add retry with backoff around `latest_block_height` for transient RPC outages.
  4. If parsing fails, check the Tendermint version's `abci_info` response shape and upgrade the shared-sequencer config/code to match.

Example fix

// before
let height = importer.latest_block_height().await?;
// after
let height = match importer.latest_block_height().await {
    Ok(h) => h,
    Err(e) => {
        tracing::warn!("tendermint RPC unreachable, retrying: {e:#}");
        tokio::time::sleep(Duration::from_secs(2)).await;
        importer.latest_block_height().await?
    }
};
Defensive patterns

Strategy: retry

Validate before calling

// pre-flight: confirm the Tendermint RPC answers before using the sequencer
let ok = reqwest::Client::new()
    .post(tendermint_rpc_api)
    .json(&serde_json::json!({"jsonrpc":"2.0","method":"abci_info","params":{},"id":1}))
    .timeout(Duration::from_secs(5))
    .send().await
    .map(|r| r.status().is_success())
    .unwrap_or(false);
if !ok { return Err(anyhow!("Tendermint RPC endpoint unreachable: {tendermint_rpc_api}")); }

Type guard

fn is_rpc_reachability_error(err: &anyhow::Error) -> bool {
    err.chain().any(|c| {
        c.downcast_ref::<reqwest::Error>().is_some()
            || c.to_string().contains("error sending request")
            || c.to_string().contains("timed out")
    })
}

Try / catch

match sequencer.latest_block_height().await {
    Ok(h) => h,
    Err(e) if is_rpc_reachability_error(&e) => {
        // transient: retry with backoff
        backoff(|| sequencer.latest_block_height().await).await?
    }
    Err(e) => return Err(e.context("non-transient tendermint RPC failure")),
}

Prevention

When it happens

Trigger: `latest_block_height()` (called from `send`) fails when: the configured `tendermint_rpc_api` URL is unreachable or wrong, the HTTP request times out or returns a transport error, the JSON-RPC response shape is unexpected, or `last_block_height` cannot be parsed as an integer.

Common situations: Misconfigured or missing `--tendermint-rpc-api` endpoint; Celestia/Tendermint node down or restarting; wrong port, TLS, or reverse-proxy setup; RPC rate limiting or firewall blocking the node; a Tendermint version returning an incompatible `abci_info` payload.

Related errors


AI-assisted analysis of FuelLabs/fuel-core@add100d30d (2026-09-05). Data as JSON: /api/errors/b659c7613fda0080. Report an issue: GitHub.