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
- Validate and, if swapped, exchange the arguments so message_block_height <= commit_block_height.
- Audit the code that derives both heights — look for off-by-one errors and DA-height vs Fuel-height confusion.
- 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
- Assert message_block_height <= commit_block_height at the API boundary and reject early.
- Double-check DA-height to Fuel-height conversions in bridging code.
- Write unit tests covering both orderings of the two height arguments.
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
- The count of leaves - messages is zero
- message da_height cannot be greater than genesis da block he
- Could not convert proof_set entry to Bytes32: {}
- {error}
- The block height subscription channel was closed: {:?}
AI-assisted analysis of FuelLabs/fuel-core@b9d4d170da (2026-08-16).
Data as JSON: /api/errors/fbd88fd8a3640651.
Report an issue: GitHub.