FuelLabs/fuel-core · error

Failed to get registry root: {}

Error message

Failed to get registry root: {}

What it means

Under fault-proving, decompression recomputes the registry root to compare against the value recorded at compression time; if reading that root from the registry DB fails, the error is wrapped as 'Failed to get registry root: {e}' (crates/compression/src/decompress.rs:123). Like its compression-side twin (compress.rs:99), the wrapped {e} carries the real storage error. This happens after transactions have already been decompressed, so the failure aborts an otherwise successful decode.

Source

Thrown at crates/compression/src/decompress.rs:123

        let tx_pointer = mint.tx_pointer_mut();
        *tx_pointer = FuelTxPointer::new(
            block.consensus_header().height,
            #[allow(clippy::arithmetic_side_effects)]
            u16::try_from(transaction_count - 1)?,
        );
    } else {
        anyhow::bail!("Last transaction is not a mint");
    }

    #[cfg(feature = "fault-proving")]
    {
        match block {
            VersionedCompressedBlock::V0(_) => {}
            VersionedCompressedBlock::V1(ref block) => {
                let registry_root_after_decompression = ctx
                    .db
                    .registry_root()
                    .map_err(|e| anyhow::anyhow!("Failed to get registry root: {}", e))?;
                let registry_root_after_compression = block.header.registry_root;
                if registry_root_after_decompression != registry_root_after_compression {
                    anyhow::bail!(
                        "Registry root mismatch. registry root after decompression: {:?}, registry root after compression: {:?}",
                        registry_root_after_decompression,
                        registry_root_after_compression
                    );
                }
            }
        }
    }

    Ok(PartialFuelBlock {
        header: block.partial_block_header(),
        transactions,
    })
}

View on GitHub (pinned to b9d4d170da)

Solutions

  1. Inspect the wrapped {e} chain for the underlying storage error.
  2. Verify the decompression side opens the same registry state that produced the block.
  3. Align fault-proving feature flags and registry DB paths across the pipeline.
  4. Restore/rebuild the registry storage if corrupted; do not retry against the same broken DB.
Defensive patterns

Strategy: try-catch

Try / catch

match compressed_block.decompress(&mut db).await {
    Err(e) if e.to_string().contains("Failed to get registry root") => {
        // surface the underlying storage error; do not retry against a broken DB
        return Err(e.context("registry storage failure during decompression"));
    }
    r => r?,
}

Prevention

When it happens

Trigger: Decompressing a V1 VersionedCompressedBlock with fault-proving enabled while registry_root() fails on the decompression-side DB (IO error, corrupted storage, wrong/closed handle).

Common situations: Registry DB corruption; pointing the verifier at the wrong database or snapshot; feature-flag drift between the compressing and decompressing binaries; concurrent DB access.

Related errors


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