linera-io/linera-protocol · error · NodeError
Missing certificates for chain {chain_id} in heights {height
Error message
Missing certificates for chain {chain_id} in heights {heights:?} What it means
Raised at the end of RemoteNode::download_certificates_by_heights when the validator answered without error but returned fewer certificates than the heights requested: the expected_heights queue is not empty after consuming everything returned. Unlike the wrong-value checks, this is usually a lagging or pruned validator that simply does not hold the certificates at those heights anymore (or not yet).
Source
Thrown at linera-core/src/remote_node.rs:275
});
}
for certificate in &certificates {
ensure!(
certificate.inner().chain_id() == chain_id,
NodeError::UnexpectedCertificateValue
);
if let Some(expected_height) = expected_heights.pop_front() {
ensure!(
expected_height == certificate.inner().height(),
NodeError::UnexpectedCertificateValue
);
} else {
return Err(NodeError::UnexpectedCertificateValue);
}
}
ensure!(
expected_heights.is_empty(),
NodeError::MissingCertificatesByHeights {
chain_id,
heights: expected_heights.into_iter().collect(),
}
);
Ok(certificates)
}
/// Checks that requesting these blobs when trying to handle this certificate is legitimate,
/// i.e. that there are no duplicates and the blobs are actually required.
pub fn check_blobs_not_found<C: Certified>(
&self,
certificate: &C,
blob_ids: &[BlobId],
) -> Result<(), NodeError> {
ensure!(!blob_ids.is_empty(), NodeError::EmptyBlobsNotFound);
let required = certificate.value().required_blob_ids();View on GitHub (pinned to 6c226ddcb3)
Solutions
- Retry against another validator that still stores (or has already synced) those heights
- Wait for the lagging validator to catch up if it is a peer-sync issue
- Download the specific certificates by hash from a full-history source (e.g. an indexer or archiver) instead of by height
- Ask the operator to disable pruning or restore from a snapshot for the affected range
Defensive patterns
Strategy: retry
Type guard
fn missing_certificates_by_heights(err: &NodeError) -> Option<&Vec<BlockHeight>> {
match err {
NodeError::MissingCertificatesByHeights { heights, .. } => Some(heights),
_ => None,
}
} Try / catch
match remote_node.download_certificates_by_heights(chain_id, heights.clone()).await {
Err(e) if missing_certificates_by_heights(&e).is_some() => {
// The listed heights are unavailable here; retry a validator with full history.
try_full_history_source(chain_id, heights).await
}
other => other,
} Prevention
- Track which validators retain full history (no pruning) and route old-height downloads to them
- Sync chains you depend on before validators prune the relevant range
- On validator restarts from snapshot, wait until catch-up completes before serving download traffic
When it happens
Trigger: Requesting heights beyond a validator's pruned history; asking a just-started validator for old blocks; requesting heights a validator will only obtain after it syncs from peers; heights for a chain the validator does not track.
Common situations: Long-running chains with validator storage pruning; fresh validator replicas during catch-up; wallets syncing very old chains; cross-chain reads pulling ancient certificates.
Understand the failure class
- SSL/TLS and certificate errors — how TLS handshakes and certificate validation fail.
Related errors
- Failed to download certificates and update local node to the
- Unexpected certificate value
- Local error handling validator response: validator still rep
- Cannot confirm a block before its predecessors: {current_blo
- 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/e6b010077019a41c.
Report an issue: GitHub.