hyperledger/fabric · error
failed to unmarshal orderer block metadata
Error message
failed to unmarshal orderer block metadata
What it means
GetConsenterMetadataFromBlock reads the ORDERER metadata, and when its Value is present unmarshals it into cb.OrdererBlockMetadata. This error means those Value bytes are not a valid OrdererBlockMetadata, so the consenter metadata nested inside cannot be reached. It wraps the underlying proto error.
Source
Thrown at protoutil/blockutils.go:169
// GetConsenterMetadataFromBlock attempts to retrieve consenter metadata from the value
// stored in block metadata at index SIGNATURES (first field). If no consenter metadata
// is found there, it falls back to index ORDERER (third field).
func GetConsenterMetadataFromBlock(block *cb.Block) (*cb.Metadata, error) {
m, err := GetMetadataFromBlock(block, cb.BlockMetadataIndex_SIGNATURES)
if err != nil {
return nil, errors.WithMessage(err, "failed to retrieve metadata")
}
// TODO FAB-15864 Remove this fallback when we can stop supporting upgrade from pre-1.4.1 orderer
if len(m.Value) == 0 {
return GetMetadataFromBlock(block, cb.BlockMetadataIndex_ORDERER)
}
obm := &cb.OrdererBlockMetadata{}
err = proto.Unmarshal(m.Value, obm)
if err != nil {
return nil, errors.Wrap(err, "failed to unmarshal orderer block metadata")
}
res := &cb.Metadata{}
err = proto.Unmarshal(obm.ConsenterMetadata, res)
if err != nil {
return nil, errors.Wrap(err, "failed to unmarshal consenter metadata")
}
return res, nil
}
// GetLastConfigIndexFromBlock retrieves the index of the last config block as
// encoded in the block metadata
func GetLastConfigIndexFromBlock(block *cb.Block) (uint64, error) {
m, err := GetMetadataFromBlock(block, cb.BlockMetadataIndex_SIGNATURES)
if err != nil {
return 0, errors.WithMessage(err, "failed to retrieve metadata")
}View on GitHub (pinned to 2736b63f8f)
Solutions
- Ensure the block was produced by a consensus type that stores OrdererBlockMetadata in the ORDERER metadata (SmartBFT), of a compatible version
- Fix test helpers (TestGoodWriteConfig etc.) to marshal a real cb.OrdererBlockMetadata into Metadata.Value
- Restore the block from a healthy orderer if the ledger is corrupted
- Inspect the wrapped proto error; if Value is intentionally absent, callers fall back to GetMetadataFromBlock(ORDERER) directly
Example fix
// before: test fixture writes opaque bytes
metadata.Value = []byte("junk")
// after
obm := &cb.OrdererBlockMetadata{ConsenterMetadata: consenterMD, LastConfig: &cb.LastConfig{Index: 0}}
metadata.Value = protoMarshal(obm) Defensive patterns
Strategy: validation
Validate before calling
m, err := protoutil.GetMetadataFromBlock(blk, cb.BlockMetadataIndex_ORDERER)
if err != nil { return err }
if len(m.Value) > 0 {
obm := &cb.OrdererBlockMetadata{}
if err := proto.Unmarshal(m.Value, obm); err != nil {
return fmt.Errorf("ORDERER metadata Value is not OrdererBlockMetadata: %w", err)
}
} Type guard
func hasParsableOrdererBlockMetadata(m *cb.Metadata) bool {
if m == nil || len(m.Value) == 0 { return false }
obm := &cb.OrdererBlockMetadata{}
return proto.Unmarshal(m.Value, obm) == nil
} Try / catch
cm, err := protoutil.GetConsenterMetadataFromBlock(blk)
if err != nil {
if strings.Contains(err.Error(), "failed to unmarshal orderer block metadata") {
log.Warnf("block %d has corrupt ORDERER metadata; using raw ORDERER metadata fallback", blk.Header.Number)
return protoutil.GetMetadataFromBlock(blk, cb.BlockMetadataIndex_ORDERER)
}
return err
} Prevention
- Only consume consenter metadata on SmartBFT channels; check consensus type first
- In tests (TestGoodWriteConfig etc.), marshal real cb.OrdererBlockMetadata into Metadata.Value
- Validate blocks with protoutil helpers before commit paths like commitBlock
- Restore corrupted blocks from a healthy orderer rather than parsing garbage bytes
When it happens
Trigger: GetConsenterMetadataFromBlock is called (from newChainSupport, commitBlock, tests) on a block whose ORDERER metadata md.Value fails proto.Unmarshal into cb.OrdererBlockMetadata.
Common situations: Blocks created by non-BFT consensus (etcdraft writes different ORDERER metadata content) consumed by SmartBFT paths; corrupted ledger data; test fixtures with placeholder Value bytes.
Understand the failure class
Background: "cannot parse invalid wire-format data", "cannot unmarshal", "failed unmarshalling": protobuf unmarshal errors explained — this error's family across 10 libraries.
Related errors
- malformed orderer metadata in block
- cannot unmarshal file part %s into a block
- failed to unmarshal BFT metadata configuration
- failed to marshal request envelope: proto: Marshal called wi
- failed to marshal request envelope
AI-assisted analysis of hyperledger/fabric@2736b63f8f (2026-09-04).
Data as JSON: /api/errors/d3a246b9c821010b.
Report an issue: GitHub.