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

  1. Verify the block metadata was produced by a compatible Fabric ordering-service version; regenerate or refetch the block from the ledger
  2. Inspect obm.ConsenterMetadata bytes (length, leading protobuf field tags) to confirm they are a serialized cb.Metadata
  3. If restoring from a snapshot/backup, re-fetch the config block from a live ordering node instead of the copy
  4. 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

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


AI-assisted analysis of hyperledger/fabric@2736b63f8f (2026-09-04). Data as JSON: /api/errors/c09cd3838b45d486. Report an issue: GitHub.