FuelLabs/fuel-core · error · StorageError

The `message_block_height` is higher than `commit_block_heig

Error message

The `message_block_height` is higher than `commit_block_height`

What it means

OnChainIterableKeyValueView::block_history_proof(message_block_height, commit_block_height) builds a Merkle inclusion proof of a message leaf within the block-commitment Merkle tree. By construction a message's block cannot be after the commit block, so message_block_height > commit_block_height is rejected up front as an invalid request rather than producing a nonsense proof.

Source

Thrown at crates/fuel-core/src/database/block.rs:96

                        .and_then(|tx| tx.ok_or(not_found!(Transactions)))
                        .map(Cow::into_owned)
                })
                .try_collect()?;
            Ok(Some(block.into_owned().uncompress(txs)))
        } else {
            Ok(None)
        }
    }
}

impl OnChainIterableKeyValueView {
    pub fn block_history_proof(
        &self,
        message_block_height: &BlockHeight,
        commit_block_height: &BlockHeight,
    ) -> StorageResult<MerkleProof> {
        if message_block_height > commit_block_height {
            Err(anyhow::anyhow!(
                "The `message_block_height` is higher than `commit_block_height`"
            ))?;
        }

        let message_merkle_metadata = self
            .storage::<FuelBlockMerkleMetadata>()
            .get(&DenseMetadataKey::Primary(*message_block_height))?
            .ok_or(not_found!(FuelBlockMerkleMetadata))?;

        let commit_merkle_metadata = self
            .storage::<FuelBlockMerkleMetadata>()
            .get(&DenseMetadataKey::Primary(*commit_block_height))?
            .ok_or(not_found!(FuelBlockMerkleMetadata))?;

        let storage = self;
        let tree: MerkleTree<FuelBlockMerkleData, _> =
            MerkleTree::load(storage, commit_merkle_metadata.version())
                .map_err(|err| StorageError::Other(anyhow::anyhow!(err)))?;

View on GitHub (pinned to b9d4d170da)

Solutions

  1. Validate and, if swapped, exchange the arguments so message_block_height <= commit_block_height.
  2. Audit the code that derives both heights — look for off-by-one errors and DA-height vs Fuel-height confusion.
  3. Return a 4xx-style invalid-argument error to API clients instead of propagating the internal error.

Example fix

// before
let proof = view.block_history_proof(&msg_height, &commit_height)?;

// after
let (msg_height, commit_height) = if msg_height <= commit_height {
    (msg_height, commit_height)
} else {
    return Err(anyhow::anyhow!("message height must be <= commit height"));
};
let proof = view.block_history_proof(&msg_height, &commit_height)?;
Defensive patterns

Strategy: validation

Validate before calling

if message_block_height > commit_block_height {
    return Err(anyhow::anyhow!(
        "invalid request: message_block_height {} > commit_block_height {}",
        message_block_height, commit_block_height
    ));
}
let proof = view.block_history_proof(&message_block_height, &commit_block_height)?;

Try / catch

match view.block_history_proof(&msg_h, &commit_h) {
    Ok(p) => Ok(p),
    Err(e) if e.to_string().contains("higher than") => {
        // argument-order bug in the caller; fix the call site, do not retry
        Err(anyhow::anyhow!("bad proof request: {}", e))
    }
    Err(e) => Err(e),
}

Prevention

When it happens

Trigger: Calling block_history_proof with the two heights swapped, or with a commit height derived incorrectly (off-by-one, wrong DA-to-Fuel height conversion), so that message_block_height exceeds commit_block_height.

Common situations: GraphQL/API message proof queries where callers pass heights in the wrong order; bridging code mapping DA heights to Fuel heights incorrectly; tests constructing proof requests by hand.

Related errors


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