FuelLabs/fuel-core · error

off-chain database height({off_chain_height}) is less than t

Error message

off-chain database height({off_chain_height}) is less than target height({target_block_height})

What it means

The off-chain counterpart of the on-chain height guard in rollback_to: the off-chain database's latest height is strictly below target_block_height, so it cannot be rolled back to the target. The off-chain DB never indexed blocks up to the requested height, indicating divergence between caller expectation and off-chain state.

Source

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

            {
                if on_chain_height == target_block_height
                    && off_chain_height == target_block_height
                    && gas_price_rolled_back
                    && compression_db_rolled_back
                {
                    break;
                }
            }

            if on_chain_height < target_block_height {
                return Err(anyhow::anyhow!(
                    "on-chain database height({on_chain_height}) \
                    is less than target height({target_block_height})"
                ));
            }

            if off_chain_height < target_block_height {
                return Err(anyhow::anyhow!(
                    "off-chain database height({off_chain_height}) \
                    is less than target height({target_block_height})"
                ));
            }

            if let Some(gas_price_chain_height) = gas_price_chain_height
                && gas_price_chain_height < target_block_height
            {
                return Err(anyhow::anyhow!(
                    "gas-price database height({gas_price_chain_height}) \
                    is less than target height({target_block_height})"
                ));
            }

            if let Some(compression_db_height) = compression_db_height
                && compression_db_height < target_block_height
            {
                return Err(anyhow::anyhow!(

View on GitHub (pinned to b9d4d170da)

Solutions

  1. Let the off-chain worker catch up to the on-chain height, then retry the rollback.
  2. If the off-chain DB is stale/corrupt, delete it and let the node rebuild indexes from on-chain data before rolling back.
  3. Always compute the rollback target from the minimum of the component databases' current heights.
Defensive patterns

Strategy: validation

Validate before calling

let off_chain = combined_db
    .off_chain()
    .latest_height_from_metadata()?
    .ok_or_else(|| anyhow::anyhow!("off-chain DB empty"))?;
if target_block_height > off_chain {
    anyhow::bail!("target {} above off-chain height {}; let the worker catch up", target_block_height, off_chain);
}

Try / catch

match combined_db.rollback_to(target, &mut shutdown) {
    Ok(()) => Ok(()),
    Err(e) if e.to_string().contains("off-chain database height") => {
        // off-chain DB lagging: rebuild or let it catch up, then retry
        wait_for_off_chain_catchup().await?;
        combined_db.rollback_to(target, &mut shutdown)
    }
    Err(e) => Err(e),
}

Prevention

When it happens

Trigger: rollback_to with a target above the off-chain database's indexed height — typical when the off-chain DB lags behind the on-chain DB (crash during indexing) or was rebuilt/reset while the target was computed from the on-chain chain.

Common situations: Off-chain worker fell behind or its DB was reset; snapshot restore mixing on-chain and off-chain from different heights; passing a target derived from chain state without checking off-chain progress.

Related errors


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