diem/diem · warning · anyhow::Error

[RoundManager] Proposer {} for block {} is not a valid propo

Error message

[RoundManager] Proposer {} for block {} is not a valid proposer for this round

What it means

RoundManager rejects an incoming proposal via ensure! when proposer_election says the author is not the valid proposer for that round. Diem/Libra BFT assigns each round a designated leader; proposals from any other validator are discarded to prevent Byzantine or stale leaders from disrupting progress.

Source

Thrown at consensus/src/round_manager.rs:639

    /// This function processes a proposal for the current round:
    /// 1. Filter if it's proposed by valid proposer.
    /// 2. Execute and add it to a block store.
    /// 3. Try to vote for it following the safety rules.
    /// 4. In case a validator chooses to vote, send the vote to the representatives at the next
    /// round.
    async fn process_proposal(&mut self, proposal: Block) -> Result<()> {
        let author = proposal
            .author()
            .expect("Proposal should be verified having an author");

        info!(
            self.new_log(LogEvent::ReceiveProposal).remote_peer(author),
            block_hash = proposal.id(),
            block_parent_hash = proposal.quorum_cert().certified_block().id(),
        );

        ensure!(
            self.proposer_election.is_valid_proposal(&proposal),
            "[RoundManager] Proposer {} for block {} is not a valid proposer for this round",
            author,
            proposal,
        );

        let block_time_since_epoch = Duration::from_micros(proposal.timestamp_usecs());

        ensure!(
            block_time_since_epoch < self.round_state.current_round_deadline(),
            "[RoundManager] Waiting until proposal block timestamp usecs {:?} \
            would exceed the round duration {:?}, hence will not vote for this round",
            block_time_since_epoch,
            self.round_state.current_round_deadline(),
        );

        observe_block(proposal.timestamp_usecs(), BlockStage::SYNCED);

View on GitHub (pinned to fc4714a8ea)

Solutions

  1. Verify your node's validator set / proposer_election configuration matches the network's on-chain configuration
  2. Check the epoch and round of the received proposal; if it's stale, the peer likely needs to sync via state sync
  3. Trace the sender peer and inspect why it thinks it is the proposer (its own config or epoch may be wrong)
  4. If this happens constantly from the same peer, coordinate with that validator operator to fix their setup
  5. Confirm consensus keys/addresses are registered correctly in the validator set
Defensive patterns

Strategy: validation

Validate before calling

// check proposer before accepting a proposal in tooling
fn expectValidProposer(author: &AccountAddress, round: u64, election: &ProposerElection) -> bool {
    election.is_valid_proposer(*author, round)
}

Prevention

When it happens

Trigger: process_proposal (via process_proposal_msg) receives a ProposalMsg whose author address does not match proposer_election's valid proposer for proposal's round.

Common situations: A misbehaving or misconfigured validator proposing out of turn; validator set changed and the peer is using an outdated proposer_election view; replayed/delayed proposal from a previous configuration; attack attempt by a non-leader.

Related errors


AI-assisted analysis of diem/diem@fc4714a8ea (2026-09-04). Data as JSON: /api/errors/f381a1ce0357868e. Report an issue: GitHub.