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

  1. Retry against another validator that still stores (or has already synced) those heights
  2. Wait for the lagging validator to catch up if it is a peer-sync issue
  3. Download the specific certificates by hash from a full-history source (e.g. an indexer or archiver) instead of by height
  4. 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

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

Related errors


AI-assisted analysis of linera-io/linera-protocol@6c226ddcb3 (2026-08-22). Data as JSON: /api/errors/e6b010077019a41c. Report an issue: GitHub.