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

  1. Ensure the block was produced by a consensus type that stores OrdererBlockMetadata in the ORDERER metadata (SmartBFT), of a compatible version
  2. Fix test helpers (TestGoodWriteConfig etc.) to marshal a real cb.OrdererBlockMetadata into Metadata.Value
  3. Restore the block from a healthy orderer if the ledger is corrupted
  4. 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

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


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