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_cache

View on GitHub (pinned to 6c226ddcb3)

Solutions

  1. Restart or rewind the exporter so it ingests each chain from height 0
  2. Verify the exporter's start position and that the source node retains block 0 (check pruning settings)
  3. 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

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


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