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

Cannot have a da height above zero without a relayer

Error message

Cannot have a da height above zero without a relayer

What it means

When fuel-core is built without the `relayer` feature, the producer hard-codes DA height 0 and rejects anything else: this is the check on the DA-height resolution path (producer.rs:173). With the feature enabled the same call instead waits for the relayer sync and returns the finalized DA height. Any block production requiring da_block_height > 0 is therefore impossible on a relayer-less build.

Source

Thrown at crates/fuel-core/src/service/adapters/producer.rs:173

impl fuel_core_producer::ports::Relayer for MaybeRelayerAdapter {
    async fn wait_for_at_least_height(
        &self,
        height: &DaBlockHeight,
    ) -> anyhow::Result<DaBlockHeight> {
        #[cfg(feature = "relayer")]
        {
            match &self.relayer_synced {
                Some(sync) => {
                    sync.await_at_least_synced(height).await?;
                    let highest = sync.get_finalized_da_height();
                    Ok(highest)
                }
                _ => Ok(*height),
            }
        }
        #[cfg(not(feature = "relayer"))]
        {
            anyhow::ensure!(
                **height == 0,
                "Cannot have a da height above zero without a relayer"
            );
            // If the relayer is not enabled, then all blocks are zero.
            Ok(0u64.into())
        }
    }

    async fn get_cost_and_transactions_number_for_block(
        &self,
        height: &DaBlockHeight,
    ) -> anyhow::Result<RelayerBlockInfo> {
        #[cfg(feature = "relayer")]
        {
            let (gas_cost, tx_count) = self
                .relayer_database
                .get_events(height)?
                .iter()

View on GitHub (pinned to b9d4d170da)

Solutions

  1. Build/run with the relayer enabled: `--features relayer` plus relayer configuration (Ethereum endpoint).
  2. Or start a fresh chain with da_block_height = 0 on non-relayer builds.
  3. Or move the chain back to relayer-enabled nodes instead of producing on this build.
  4. Verify the running binary actually includes the feature (build flags, feature list).
Defensive patterns

Strategy: validation

Validate before calling

// Before block production, assert build/DA-height compatibility:
fn can_handle_da_height(da_block_height: u64) -> bool {
    if cfg!(feature = "relayer") {
        true // heights validated against the relayer at runtime
    } else {
        da_block_height == 0
    }
}
assert!(can_handle_da_height(config.chain_conf.da_block_height.into()));

Type guard

fn relayer_enabled() -> bool {
    cfg!(feature = "relayer")
}

Try / catch

if let Err(e) = produce_result {
    if e.to_string().contains("without a relayer") {
        // fatal configuration mismatch: rebuild with `relayer` feature or
        // restart the chain with da_block_height = 0
        return Err(anyhow!("node built without relayer but chain needs DA heights > 0"));
    }
    return Err(e);
}

Prevention

When it happens

Trigger: Producing a block on a non-relayer build where the chain config / snapshot sets da_block_height above zero, so **height != 0 fails the ensure!.

Common situations: Continuing a chain created by a relayer-enabled deployment on a binary compiled without the feature; custom chains with da_block_height set; downgrading a deployment to a build lacking the feature.

Related errors


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