linera-io/linera-protocol · error · ChainError

BlockHeightOverflow

BlockHeightOverflow

Error message

Sequence numbers above the maximal value are not usable for blocks

What it means

Guard in ChainManager::check_proposed_block: a proposed block's height must be strictly below BlockHeight::MAX (u64::MAX) so that incrementing the height after certification can never fail. A block at the maximal height could be certified but never extended, deadlocking the chain, so the proposal is refused up front.

Source

Thrown at linera-chain/src/manager.rs:296

    ///
    /// Having a leader timeout certificate in any given round causes the next one to become
    /// current. Seeing a validated block certificate or a valid proposal in any round causes that
    /// round to become current, unless a higher one already is.
    pub fn current_round(&self) -> Round {
        *self.current_round.get()
    }

    /// Verifies that a proposed block is relevant and should be handled.
    pub fn check_proposed_block(&self, proposal: &BlockProposal) -> Result<Outcome, ChainError> {
        let new_block = &proposal.content.block;
        let new_round = proposal.content.round;
        if let Some(old_proposal) = self.proposed.get() {
            if old_proposal.content == proposal.content {
                return Ok(Outcome::Skip); // We have already seen this proposal; nothing to do.
            }
        }
        // When a block is certified, incrementing its height must succeed.
        ensure!(
            new_block.height < BlockHeight::MAX,
            ChainError::BlockHeightOverflow
        );
        let current_round = self.current_round();
        match new_round {
            // The proposal from the fast round may still be relevant as a locking block, so
            // we don't compare against the current round here.
            Round::Fast => {}
            Round::MultiLeader(_) | Round::SingleLeader(0) => {
                // If the fast round has not timed out yet, only a super owner is allowed to open
                // a later round by making a proposal.
                ensure!(
                    self.is_super(&proposal.owner()) || !current_round.is_fast(),
                    ChainError::WrongRound(current_round)
                );
                // After the fast round, proposals older than the current round are obsolete.
                ensure!(
                    new_round >= current_round,

View on GitHub (pinned to 6c226ddcb3)

Solutions

  1. If hit in tests or fuzzing, use a fresh chain or reset the fixture instead of extending one at u64::MAX
  2. If ever hit in production, the chain is exhausted and cannot be extended further; migrate state to a new chain
Defensive patterns

Strategy: validation

Validate before calling

// Refuse to build or submit a proposal at the maximal height.
if block.height >= BlockHeight::MAX {
    return Err(my::Error::ChainExhausted);
}

Type guard

fn is_block_height_overflow(e: &ChainError) -> bool {
    matches!(e, ChainError::BlockHeightOverflow)
}

Prevention

When it happens

Trigger: Submitting (via try_handle_block_proposal) a block proposal whose block.height equals BlockHeight::MAX.

Common situations: Practically unreachable in production because it requires 2^64 blocks on one chain; occasionally produced by fuzzers or unit tests that construct blocks at extreme heights.

Related errors


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