FuelLabs/fuel-core · error

off-chain database doesn't have height

Error message

off-chain database doesn't have height

What it means

Same rollback_to prelude as the on-chain check, but for the off-chain (indexes, GraphQL views) database: off_chain().latest_height_from_metadata() returned None, so the off-chain database has no recorded height and the combined rollback cannot proceed. Rollback is only defined for databases that have processed at least genesis.

Solutions

  1. Let the node run so the off-chain worker catches up and records a height, then retry the rollback.
  2. If the off-chain DB is disposable, delete it entirely and let the node rebuild it (off-chain data is derivable from on-chain state).
  3. Restore both on-chain and off-chain databases from the same consistent snapshot.
Defensive patterns

Strategy: validation

Validate before calling

let off_chain = combined_db.off_chain().latest_height_from_metadata()?;
if off_chain.is_none() {
    anyhow::bail!("off-chain DB not initialized; let the node index genesis first");
}
combined_db.rollback_to(target, &mut shutdown)?;

Try / catch

match combined_db.rollback_to(target, &mut shutdown) {
    Ok(()) => Ok(()),
    Err(e) if e.to_string().contains("off-chain database doesn't have height") => {
        // off-chain data is derivable: rebuild it, then retry
        rebuild_off_chain_db().and_then(|_| combined_db.rollback_to(target, &mut shutdown))
    }
    Err(e) => Err(e),
}

Prevention

When it happens

Trigger: rollback_to invoked when the off-chain database is empty or its metadata was never written — typically an off-chain DB created but never synced, or one whose metadata column was wiped while the on-chain DB has data.

Common situations: Mixed/partially restored database directories (on-chain restored, off-chain missing); deleting only the off-chain DB files to 'reset indexes' and then running rollback tooling; node crashed during first off-chain commit before metadata flush.

Related errors


AI-assisted analysis of FuelLabs/fuel-core@b9d4d170da (2026-08-16). Data as JSON: /api/errors/e054c495e8bf815c. Report an issue: GitHub.

Appendix: source

Thrown at crates/fuel-core/src/combined_database.rs:478

    /// Rollbacks the state of the blockchain to a specific block height.
    pub fn rollback_to<S>(
        &mut self,
        target_block_height: BlockHeight,
        shutdown_listener: &mut S,
    ) -> anyhow::Result<()>
    where
        S: ShutdownListener,
    {
        while !shutdown_listener.is_cancelled() {
            let on_chain_height = self
                .on_chain()
                .latest_height_from_metadata()?
                .ok_or(anyhow::anyhow!("on-chain database doesn't have height"))?;

            let off_chain_height = self
                .off_chain()
                .latest_height_from_metadata()?
                .ok_or(anyhow::anyhow!("off-chain database doesn't have height"))?;

            let gas_price_chain_height =
                self.gas_price().latest_height_from_metadata()?;
            let gas_price_rolled_back = is_equal_or_less_than_or_none(
                gas_price_chain_height,
                target_block_height,
            );

            let compression_db_height =
                self.compression().latest_height_from_metadata()?;
            let compression_db_rolled_back =
                is_equal_or_less_than_or_none(compression_db_height, target_block_height);

            #[cfg(feature = "rpc")]
            {
                let block_aggregation_storage_height = self
                    .block_aggregation_storage()
                    .latest_height_from_metadata()?;

View on GitHub (pinned to b9d4d170da)