linera-io/linera-protocol · error · ChainError
Cannot confirm a block before its predecessors: {current_blo
Error message
Cannot confirm a block before its predecessors: {current_block_height:?} What it means
ChainTipState::already_validated_block (linera-chain/src/chain.rs:429-437) errors with MissingEarlierBlocks when a certificate's height is strictly above the chain's next_block_height — the chain is missing one or more predecessor blocks, so the certificate cannot be processed yet. It is the gatekeeper for process_timeout (linera-core/src/chain_worker/state.rs:793) and process_validated_block (state.rs:892), both of which must receive certificates in height order. This is a synchronization error, not a permanent rejection: once the gap is filled, the same certificate will process.
Source
Thrown at linera-chain/src/chain.rs:430
pub fn verify_block_chaining(&self, new_block: &ProposedBlock) -> Result<(), ChainError> {
ensure!(
new_block.height == self.next_block_height,
ChainError::UnexpectedBlockHeight {
expected_block_height: self.next_block_height,
found_block_height: new_block.height
}
);
ensure!(
new_block.previous_block_hash == self.block_hash,
ChainError::UnexpectedPreviousBlockHash
);
Ok(())
}
/// Returns `true` if the validated block's height is below the tip height. Returns an error if
/// it is higher than the tip.
pub fn already_validated_block(&self, height: BlockHeight) -> Result<bool, ChainError> {
ensure!(
self.next_block_height >= height,
ChainError::MissingEarlierBlocks {
current_block_height: self.next_block_height,
}
);
Ok(self.next_block_height > height)
}
}
impl<C> ChainStateView<C>
where
C: Context + Clone + 'static,
C::Extra: ExecutionRuntimeContext,
{
/// Returns the [`ChainId`] of the chain this [`ChainStateView`] represents.
pub fn chain_id(&self) -> ChainId {
self.context().extra().chain_id()
}View on GitHub (pinned to 6c226ddcb3)
Solutions
- Fetch and process the missing confirmed blocks (query the sender chain or peer validators) up to the certificate's height, then resubmit the certificate
- Ensure your delivery layer processes blocks in height order per chain
- Retry the same certificate after synchronization — it is not poisoned
- If a node persistently lags, check its storage health and catch it up via a full chain query
Example fix
// before: submitting the certificate directly
worker.handle_validated_certificate(cert).await?;
// after: fill the gap first, then retry
let tip = chain_info.next_block_height;
if cert.block().header.height > tip {
for h in tip..cert.block().header.height {
let missing = fetch_confirmed_block(chain_id, h).await?;
worker.handle_confirmed_certificate(missing).await?;
}
}
worker.handle_validated_certificate(cert).await?; Defensive patterns
Strategy: retry
Validate before calling
// Before submitting a certificate, check the chain can anchor it:
let next = chain_info.next_block_height;
if cert_height > next {
// gap: process confirmed blocks [next, cert_height) first
for h in next..cert_height {
let block = fetch_confirmed_block(chain_id, h).await?;
worker.handle_confirmed_block(block).await?;
}
} Try / catch
match worker.handle_certificate(cert).await {
Err(WorkerError::ChainError(ChainError::MissingEarlierBlocks { current_block_height })) => {
// sync missing heights (current_block_height..cert height), then retry the SAME certificate
}
other => other?,
} Prevention
- Deliver blocks and certificates in height order per chain
- After a node restart or storage restore, catch up before processing live traffic
- Remember this error is transient — the certificate becomes processable once the gap is filled
When it happens
Trigger: Delivering a ValidatedBlockCertificate or TimeoutCertificate for height 10 while the local chain state is at next_block_height 7; a validator that skipped/restarted and lost heights receiving current certificates; cross-chain message handling that delivers a recipient update before the sender's earlier blocks were processed.
Common situations: Validators lagging behind the leader and receiving newer certificates first; network reordering; client submitting a higher block without first syncing handle_confirmed_block for the missing heights; storage restored from an old snapshot.
Related errors
- Certificate justification commitment does not match its just
- Certificate unlocking round does not match the top of its ju
- Justification chain must lie in rounds strictly below the ce
- Certificate carries the first-round attestation but was not
- Cannot vote for block proposal of chain {chain_id} because {
AI-assisted analysis of linera-io/linera-protocol@6c226ddcb3 (2026-08-22).
Data as JSON: /api/errors/9b12d10ff341a268.
Report an issue: GitHub.