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

Same RelayerPort adapter but the not(relayer) branch (crates/fuel-core/src/service/adapters/consensus_module.rs:82). The binary was compiled without the relayer feature, so there is no DA synchronization source at all; the adapter therefore rejects any block whose header da_height is above zero, since it could never verify DA finality for it.

Source

Thrown at crates/fuel-core/src/service/adapters/consensus_module.rs:82

        &self,
        da_height: &DaBlockHeight,
        _max_da_lag: &DaBlockHeight,
    ) -> anyhow::Result<()> {
        #[cfg(feature = "relayer")]
        {
            if let Some(sync) = &self.relayer_synced {
                let current_height = sync.get_finalized_da_height();
                anyhow::ensure!(
                    da_height.saturating_sub(*current_height) <= **_max_da_lag,
                    "Relayer is too far out of sync"
                );
                sync.await_at_least_synced(da_height).await?;
            }
            Ok(())
        }
        #[cfg(not(feature = "relayer"))]
        {
            anyhow::ensure!(
                **da_height == 0,
                "Cannot have a da height above zero without a relayer"
            );
            Ok(())
        }
    }
}

View on GitHub (pinned to b9d4d170da)

Solutions

  1. Build and run the node with the relayer feature enabled (cargo build --features relayer or the full preset binary)
  2. If DA is genuinely unused in this deployment, fix producers so blocks are created with da_height = 0
  3. Reject the offending block at the p2p/import boundary instead of letting it reach consensus

Example fix

# before: cargo build -p fuel-core --no-default-features
# after:  cargo build -p fuel-core --features relayer
// (or, where DA is unused, produce blocks with header da_height == 0)
Defensive patterns

Strategy: validation

Validate before calling

// library users building blocks without the relayer feature:
fn valid_da_height(cfg: &ProducerConfig, da_height: DaBlockHeight) -> bool {
    #[cfg(not(feature = "relayer"))]
    { da_height == DaBlockHeight(0) }
    #[cfg(feature = "relayer")]
    { true }
}

Type guard

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

Try / catch

if let Err(e) = port.await_until_if_in_range(&da_height, &lag).await {
    if e.to_string().contains("without a relayer") {
        // build/feature mismatch or bad producer: fail loudly, retrying cannot help
    }
}

Prevention

When it happens

Trigger: Running a fuel-core build without the relayer feature (MaybeRelayerAdapter has no relayer_synced path) while producing or importing a block whose da_height > 0.

Common situations: Local/dev builds with default features receiving blocks from a DA-connected network; a buggy or malicious producer setting a non-zero da_height; embedding fuel-core as a library without enabling optional relayer features.

Related errors


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