linera-io/linera-protocol · error · ExporterError
BadInitialization
BadInitialization
Error message
ExporterError::BadInitialization
What it means
The exporter storage layer processes blocks for chains it has not seen before via index_chain, which must register them from their height-0 block. This BadInitialization is raised when a chain's first indexed block is not at BlockHeight::ZERO — the chain cannot be registered from a mid-chain block.
Source
Thrown at linera-exporter/src/storage.rs:303
if let Some(status) = self.chain_states_cache.get(&block_id.chain_id) {
return Ok(status.height >= block_id.height);
}
if let Some(status) = self
.exporter_state_view
.get_chain_status(&block_id.chain_id)
.await?
{
let result = status.height >= block_id.height;
self.chain_states_cache.insert(block_id.chain_id, status);
return Ok(result);
}
Err(ExporterError::UnprocessedChain)
}
pub(super) async fn index_chain(&mut self, block_id: &BlockId) -> Result<(), ExporterError> {
ensure!(
block_id.height == BlockHeight::ZERO,
ExporterError::BadInitialization
);
self.exporter_state_view.initialize_chain(*block_id).await?;
self.chain_states_cache
.insert(block_id.chain_id, (*block_id).into());
Ok(())
}
pub(super) async fn index_block(&mut self, block_id: &BlockId) -> Result<bool, ExporterError> {
if block_id.height == BlockHeight::ZERO {
self.index_chain(block_id).await?;
return Ok(true);
}
if self.exporter_state_view.index_block(*block_id).await? {
self.chain_states_cacheView on GitHub (pinned to 6c226ddcb3)
Solutions
- Restart or rewind the exporter so it ingests each chain from height 0
- Verify the exporter's start position and that the source node retains block 0 (check pruning settings)
- For chains legitimately discovered mid-way, pre-seed the exporter state so the chain is already registered when the later block arrives
Example fix
// before
storage.index_block(&block_id).await?; // first block seen for this chain is height 42 -> BadInitialization
// after
// ingest the chain genesis first, then the later block
storage.index_block(&BlockId { chain_id, height: BlockHeight::ZERO, hash: genesis_hash }).await?;
storage.index_block(&block_id).await?; Defensive patterns
Strategy: validation
Validate before calling
fn is_chain_genesis(block_id: &BlockId) -> bool {
block_id.height == BlockHeight::ZERO
}
// before indexing an unknown chain, ensure its genesis is indexed first:
if !exporter_knows_chain(&block_id.chain_id) {
anyhow::ensure!(is_chain_genesis(block_id), "first block for a new chain must be height 0");
} Type guard
fn is_chain_genesis(block_id: &BlockId) -> bool {
block_id.height == BlockHeight::ZERO
} Prevention
- Ingest chains from height 0; rewind the exporter when a chain appears mid-stream
- Check pruning/retention on the source node so block 0 stays available
- Pre-register chains in exporter state before pointing it at later blocks
When it happens
Trigger: index_block forwards a BlockId for an unknown chain whose height is greater than 0, so index_chain falls through to initialize_chain with a non-genesis block.
Common situations: Exporter attached to an already-running network; exporter started with an offset or after chains were created; gaps in the exporter's source data so block 0 is never ingested.
Related errors
- BadInitialization
- no signer found for owner ${owner}
- --bulk-height-range must be `auto` or `FROM:TO`
- Cannot confirm a block before its predecessors: {current_blo
- BlockHeightOverflow
AI-assisted analysis of linera-io/linera-protocol@6c226ddcb3 (2026-08-22).
Data as JSON: /api/errors/e5e20b99737318f0.
Report an issue: GitHub.