hyperledger/fabric · error
expected metadata in block to be [view_id:%d latest_sequence
Error message
expected metadata in block to be [view_id:%d latest_sequence:%d] but got [view_id:%d latest_sequence:%d]
What it means
In Hyperledger Fabric's SmartBFT ordering consensus, the proposer places SmartBFT ViewMetadata (view_id, latest_sequence) both in the proposal and in the block's orderer metadata. During VerifyProposal, verifyBlockDataAndMetadata unmarshals the metadata from the proposal and proto-Compares it with the metadata embedded in the block. This error means the two copies disagree, so the block header's metadata was tampered with or produced by a node on a different view/sequence than the proposal.
Source
Thrown at orderer/consensus/smartbft/verifier.go:295
ordererMetadataFromSignature := &cb.OrdererBlockMetadata{}
if err := proto.Unmarshal(signatureMetadata.Value, ordererMetadataFromSignature); err != nil {
return nil, errors.Wrap(err, "failed unmarshaling OrdererBlockMetadata")
}
// Ensure the view metadata in the block signature and in the proposal are the same
metadataInBlock := &smartbftprotos.ViewMetadata{}
if err := proto.Unmarshal(ordererMetadataFromSignature.ConsenterMetadata, metadataInBlock); err != nil {
return nil, errors.Wrap(err, "failed unmarshaling smartbft metadata from block")
}
metadataFromProposal := &smartbftprotos.ViewMetadata{}
if err := proto.Unmarshal(metadata, metadataFromProposal); err != nil {
return nil, errors.Wrap(err, "failed unmarshaling smartbft metadata from proposal")
}
if !proto.Equal(metadataInBlock, metadataFromProposal) {
return nil, errors.Errorf(
"expected metadata in block to be [view_id:%d latest_sequence:%d] but got [view_id:%d latest_sequence:%d]",
metadataFromProposal.GetViewId(), metadataFromProposal.GetLatestSequence(),
metadataInBlock.GetViewId(), metadataInBlock.GetLatestSequence(),
)
}
rtc := v.RuntimeConfig.Load().(RuntimeConfig)
lastConfig := rtc.LastConfigBlock.Header.Number
if protoutil.IsConfigBlock(block) {
lastConfig = block.Header.Number
}
// Verify last config
if ordererMetadataFromSignature.LastConfig == nil {
return nil, errors.Errorf("last config is nil")
}
View on GitHub (pinned to 2736b63f8f)
Solutions
- Confirm all consenters run the same Fabric version (SmartBFT metadata format changed across releases) and upgrade stragglers.
- Restart the ordering service so the node re-enters the current view and regenerates consistent proposal metadata.
- If a leader repeatedly produces this mismatch, force a view change (leader timeout/election) to elect a healthy leader.
- Check on-disk ledger integrity of the block metadata; restore the node from a snapshot/backup if corruption is suspected.
- Compare ViewId/LatestSequence in the log message to determine whether the divergence is a view change (view_id) or sequence lag (latest_sequence) and fix accordingly (stale leader vs. slow node).
Example fix
// before (stale leader proposal metadata after view change)
metadataFromProposal: {ViewId: 3, LatestSequence: 120}
metadataInBlock: {ViewId: 4, LatestSequence: 120} -> error
// after: force leader re-proposal in the current view so both carry ViewId 4
metadataFromProposal: {ViewId: 4, LatestSequence: 120}
metadataInBlock: {ViewId: 4, LatestSequence: 120} Defensive patterns
Strategy: validation
Validate before calling
md := &common.ViewMetadata{}
if err := proto.Unmarshal(metadataInBlock, md); err != nil { return err }
if md.GetViewId() != currentView || md.GetLatestSequence() != currentSeq {
return fmt.Errorf("block metadata view/seq %d/%d != current %d/%d", md.GetViewId(), md.GetLatestSequence(), currentView, currentSeq)
} Try / catch
result, err := verifier.VerifyProposal(prop)
if err != nil {
if strings.Contains(err.Error(), "expected metadata in block") {
// force view change / re-sync before retrying
}
return err
} Prevention
- Keep all consenters on the same Fabric version
- After a view change, always re-propose with freshly generated metadata
- Monitor view_id/latest_sequence in logs to catch lagging nodes early
When it happens
Trigger: VerifyProposal -> verifyBlockDataAndMetadata: proto.Equal(metadataInBlock, metadataFromProposal) is false, i.e. the ViewMetadata in the block (from the signature/verification path) has a different ViewId or LatestSequence than the metadata attached to the proposal being verified. Also triggered when the proposal's metadata bytes fail to reflect the view change (view_id bump) or sequence advance that the block already carries.
Common situations: A leader assembling a proposal after a view change but reusing stale block metadata; mixed Fabric versions across consenters with different metadata encoding; a corrupted or manually modified block; nodes catching up after a crash so their persisted view_id/latest_sequence diverge from the channel's actual view.
Related errors
- failed unmarshalling OrdererBlockMetadata
- expected verification sequence %d, but proposal has %d
- last config is nil
- mismatched block header
- consenter metadata in OrdererBlockMetadata doesn't match pro
AI-assisted analysis of hyperledger/fabric@2736b63f8f (2026-09-04).
Data as JSON: /api/errors/bbc56b372e2447f0.
Report an issue: GitHub.