hyperledger/fabric · error
failed to unmarshal consenter metadata
Error message
failed to unmarshal consenter metadata
What it means
GetConsenterMetadataFromBlock extracts the consenter metadata from a block's orderer metadata. After unmarshalling the OrdererBlockMetadata, it attempts to proto-unmarshal the ConsenterMetadata field into cb.Metadata; this error wraps any failure of that unmarshal, meaning the consenter metadata bytes are corrupt, empty-but-present, or not a valid protobuf Metadata message.
Source
Thrown at protoutil/blockutils.go:175
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")
}
// TODO FAB-15864 Remove this fallback when we can stop supporting upgrade from pre-1.4.1 orderer
if len(m.Value) == 0 {
m, err := GetMetadataFromBlock(block, cb.BlockMetadataIndex_LAST_CONFIG)
if err != nil {
return 0, errors.WithMessage(err, "failed to retrieve metadata")
}View on GitHub (pinned to 2736b63f8f)
Solutions
- Verify the block metadata was produced by a compatible Fabric ordering-service version; regenerate or refetch the block from the ledger
- Inspect obm.ConsenterMetadata bytes (length, leading protobuf field tags) to confirm they are a serialized cb.Metadata
- If restoring from a snapshot/backup, re-fetch the config block from a live ordering node instead of the copy
- Update Fabric binaries/protos so producer and consumer agree on the OrdererBlockMetadata schema
Example fix
// before
res := &cb.Metadata{}
if err := proto.Unmarshal(obm.ConsenterMetadata, res); err != nil {
return nil, errors.Wrap(err, "failed to unmarshal consenter metadata")
}
// after
if len(obm.ConsenterMetadata) == 0 {
return nil, errors.New("consenter metadata is absent in orderer block metadata")
}
res := &cb.Metadata{}
if err := proto.Unmarshal(obm.ConsenterMetadata, res); err != nil {
logger.Errorf("consenter metadata bytes (%d) not a valid cb.Metadata: %v", len(obm.ConsenterMetadata), err)
return nil, errors.Wrap(err, "failed to unmarshal consenter metadata")
} Defensive patterns
Strategy: validation
Validate before calling
func hasConsenterMetadata(block *cb.Block) bool {
md := block.GetMetadata().GetMetadata()
if len(md) < int(cb.BlockMetadataIndex_ORDERER)+1 || len(md[cb.BlockMetadataIndex_ORDERER]) == 0 {
return false
}
obm := &cb.OrdererBlockMetadata{}
if proto.Unmarshal(md[cb.BlockMetadataIndex_ORDERER], obm) != nil {
return false
}
return len(obm.GetConsenterMetadata()) > 0
} Type guard
func isParseableMetadata(raw []byte) (*cb.Metadata, bool) {
m := &cb.Metadata{}
if len(raw) == 0 || proto.Unmarshal(raw, m) != nil {
return nil, false
}
return m, true
} Try / catch
res, err := GetConsenterMetadataFromBlock(block)
if err != nil {
logger.Warnf("skipping block %d, bad consenter metadata: %v", block.GetHeader().GetNumber(), err)
return nil // or re-fetch the block
} Prevention
- Keep all Fabric ordering/peer binaries on the same version so OrdererBlockMetadata schemas match
- Never hand-edit or truncate block files; use ledger tooling for migration
- Check metadata entry length before unmarshalling
- Re-fetch blocks from a live ordering node when parsing fails
When it happens
Trigger: Calling GetConsenterMetadataFromBlock on a block whose ORDERER metadata entry contains a ConsenterMetadata field that fails proto.Unmarshal — e.g. bytes written by a different metadata schema, truncated/corrupt block data, or a nil/empty ConsenterMetadata where the underlying proto unmarshal of malformed bytes fails.
Common situations: Blocks produced by mismatched ordering-service versions (BFT vs non-BFT metadata layouts), blocks copied or truncated during ledger migration/snapshot restore, or reading blocks from a foreign/incompatible channel genesis block.
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
- failed to deserialize values
- error converting envelope to config update: %s
- failed to unmarshal response for transaction %s
- unmarshalling ChaincodeQueryResponse failed
- could not unmarshal chaincode package to CDS or SignedCDS
AI-assisted analysis of hyperledger/fabric@2736b63f8f (2026-09-04).
Data as JSON: /api/errors/c09cd3838b45d486.
Report an issue: GitHub.