hyperledger/fabric · error
expected verification sequence %d, but proposal has %d
Error message
expected verification sequence %d, but proposal has %d
What it means
VerifyProposal compares the verifier's current verification sequence (the config sequence under which signatures are verified) with the sequence recorded in the proposal. A mismatch means the proposal was produced against a stale or newer channel config, so it is rejected.
Source
Thrown at orderer/consensus/smartbft/verifier.go:117
func (v *Verifier) VerifyProposal(proposal types.Proposal) ([]types.RequestInfo, error) {
block, err := ProposalToBlock(proposal)
if err != nil {
return nil, err
}
rtc := v.RuntimeConfig.Load().(RuntimeConfig)
if err := verifyHashChainAndDataHash(block, rtc.LastCommittedBlockHash); err != nil {
return nil, err
}
requests, err := v.verifyBlockDataAndMetadata(block, proposal.Metadata)
if err != nil {
return nil, err
}
verificationSeq := v.VerificationSequence()
if verificationSeq != uint64(proposal.VerificationSequence) {
return nil, errors.Errorf("expected verification sequence %d, but proposal has %d", verificationSeq, proposal.VerificationSequence)
}
return requests, nil
}
// RequestsFromProposal converts proposal to []RequestInfo
func (v *Verifier) RequestsFromProposal(proposal types.Proposal) []types.RequestInfo {
block, err := ProposalToBlock(proposal)
if err != nil {
return []types.RequestInfo{}
}
if block.Data == nil {
return []types.RequestInfo{}
}
var res []types.RequestInfo
for _, txn := range block.Data.Data {View on GitHub (pinned to 2736b63f8f)
Solutions
- Ensure all replicas commit the latest config block and catch up their ledger before participating
- Trigger re-proposal/retry: the leader will reassemble the proposal under the current verification sequence
- Check network connectivity of the lagging node so it receives config blocks promptly
- Restart the lagging orderer after ledger catch-up to refresh its runtime config
Defensive patterns
Strategy: retry
Validate before calling
seq := v.VerificationSequence()
if seq != uint64(proposal.VerificationSequence) {
return fmt.Errorf("stale proposal: have %d want %d", proposal.VerificationSequence, seq)
} Try / catch
if err := VerifyProposal(proposal, ...); err != nil {
if strings.Contains(err.Error(), "expected verification sequence") {
// wait for ledger catch-up / let leader re-propose
}
} Prevention
- Keep all replicas in sync on config blocks before proposals
- Avoid replaying old proposals after config updates
- Monitor replication lag across orderer nodes
When it happens
Trigger: A node whose channel config has advanced (verification sequence bumped) receiving a proposal assembled by a leader still on the old config; partitioned or lagging consensus replicas during config updates.
Common situations: Config update (e.g. adding a consenter) committed by most nodes while one replica lags; leader election racing with a config change; replaying an old proposal after a config commit.
Related errors
- expected metadata in block to be [view_id:%d latest_sequence
- mismatched block header
- consenter metadata in OrdererBlockMetadata doesn't match pro
- consenter options type mismatch
- unknown orderer type: %s
AI-assisted analysis of hyperledger/fabric@2736b63f8f (2026-09-04).
Data as JSON: /api/errors/0099d1da6df3b2e5.
Report an issue: GitHub.