linera-io/linera-protocol · warning · ChainError

InsufficientRoundStrict

InsufficientRoundStrict

Error message

Round number should be greater than {0:?}

What it means

The round of a validator's validation votes is only allowed to increase: check_proposed_block rejects any proposal whose round is not strictly greater than the round of the manager's latest validated vote. This keeps signed validation votes monotonic.

Source

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

                    ChainError::WrongRound(current_round)
                );
                // After the fast round, proposals older than the current round are obsolete.
                ensure!(
                    new_round >= current_round,
                    ChainError::InsufficientRound(new_round)
                );
            }
            Round::SingleLeader(_) | Round::Validator(_) => {
                // After the first single-leader round, only proposals from the current round are relevant.
                ensure!(
                    new_round == current_round,
                    ChainError::WrongRound(current_round)
                );
            }
        }
        // The round of our validation votes is only allowed to increase.
        if let Some(vote) = self.validated_vote() {
            ensure!(
                new_round > vote.round,
                ChainError::InsufficientRoundStrict(vote.round)
            );
        }
        // A proposal that isn't newer than the locking block is not relevant anymore.
        if let Some(locking_block) = self.locking_block.get() {
            ensure!(
                locking_block.round() < new_round,
                ChainError::MustBeNewerThanLockingBlock(new_block.height, locking_block.round())
            );
        }
        // If we have voted to confirm a block, we may only vote to validate a *different* block
        // if a validated block certificate justifies it from a round strictly after our
        // confirmation. The validation vote will then sign the unlocking round `certificate.round`,
        // and since our confirmation is in an earlier round, the claim "I have not voted to confirm
        // a different block in any round at or above the unlocking round" stays truthful.
        //
        // Re-validating the very block we confirmed is also allowed, but the certificate must

View on GitHub (pinned to 6c226ddcb3)

Solutions

  1. Move to a strictly higher round (collect timeout votes/certificates to advance the round) before re-proposing
  2. Drop the conflicting proposal; it cannot be validated at or below the vote round
Defensive patterns

Strategy: validation

Validate before calling

let info = client.chain_info(chain_id).await?;
if let Some(vote) = info.manager.validated_vote() {
    if proposal.content.round <= vote.round {
        // Validation votes only move forward: advance the round first.
        return advance_round_via_timeouts(&client, chain_id).await;
    }
}

Type guard

fn is_insufficient_round_strict(e: &ChainError) -> bool {
    matches!(e, ChainError::InsufficientRoundStrict(_))
}

Prevention

When it happens

Trigger: A proposal (often conflicting or a duplicate) arrives with round <= validated_vote.round while the manager has already voted to validate a block in that round.

Common situations: Two leaders active in the same round; retrying a proposal after the validator already voted on another block in that round; client resubmitting from stale state.

Related errors


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