hyperledger/fabric · error

no metadata in block

Error message

no metadata in block

What it means

GetMetadataFromBlock retrieves the cb.Metadata message at a given BlockMetadataIndex. It returns 'no metadata in block' when block.Metadata is nil, i.e. the block carries no metadata section at all, so no index can be read. This is a precondition check before index bounds and unmarshalling.

Source

Thrown at protoutil/blockutils.go:127

	if err != nil {
		return "", err
	}

	if payload.Header == nil {
		return "", errors.New("failed to retrieve channel id - payload header is empty")
	}
	chdr, err := UnmarshalChannelHeader(payload.GetHeader().GetChannelHeader())
	if err != nil {
		return "", err
	}

	return chdr.ChannelId, nil
}

// GetMetadataFromBlock retrieves metadata at the specified index.
func GetMetadataFromBlock(block *cb.Block, index cb.BlockMetadataIndex) (*cb.Metadata, error) {
	if block.Metadata == nil {
		return nil, errors.New("no metadata in block")
	}

	if len(block.Metadata.Metadata) <= int(index) {
		return nil, errors.Errorf("no metadata at index [%s]", index)
	}

	md := &cb.Metadata{}
	err := proto.Unmarshal(block.Metadata.Metadata[index], md)
	if err != nil {
		return nil, errors.Wrapf(err, "error unmarshalling metadata at index [%s]", index)
	}
	return md, nil
}

// GetMetadataFromBlockOrPanic retrieves metadata at the specified index, or
// panics on error
func GetMetadataFromBlockOrPanic(block *cb.Block, index cb.BlockMetadataIndex) *cb.Metadata {
	md, err := GetMetadataFromBlock(block, index)

View on GitHub (pinned to 2736b63f8f)

Solutions

  1. Guard callers with if block.Metadata == nil before calling, or use GetMetadataFromBlockOrPanic only where nil is impossible
  2. Ensure blocks always come from protoutil/ledger write paths that populate metadata (commitBlock with WriteBlock)
  3. Regenerate or re-fetch the block if the ledger is corrupt
  4. Fix test builders to set Metadata with the required indices (SIGNATURES, LAST_CONFIG, ORDERER)

Example fix

// before
md, err := protoutil.GetMetadataFromBlock(blk, cb.BlockMetadataIndex_SIGNATURES)
// after
if blk == nil || blk.Metadata == nil {
    return errors.New("block has no metadata")
}
md, err := protoutil.GetMetadataFromBlock(blk, cb.BlockMetadataIndex_SIGNATURES)
Defensive patterns

Strategy: type-guard

Validate before calling

if blk == nil || blk.Metadata == nil {
    return errors.New("block has no metadata section")
}
md, err := protoutil.GetMetadataFromBlock(blk, cb.BlockMetadataIndex_SIGNATURES)

Type guard

func hasMetadataSection(b *cb.Block) bool {
    return b != nil && b.Metadata != nil
}

Try / catch

md, err := protoutil.GetMetadataFromBlock(blk, idx)
if err != nil {
    if err.Error() == "no metadata in block" {
        log.Warnf("block %d lacks metadata; treating as invalid", blk.Header.Number)
        return errInvalidBlock
    }
    return err
}

Prevention

When it happens

Trigger: Calling GetMetadataFromBlock (directly or via GetMetadataFromBlockOrPanic, GetConsenterMetadataFromBlock, GetLastConfigIndexFromBlock, verifyBlockDataAndMetadata) on a block whose Metadata field is nil.

Common situations: Blocks constructed programmatically in tests without Metadata; corrupted ledger entries with stripped metadata; genesis blocks from tooling that omits metadata; deserialization paths that partially populate cb.Block.

Related errors


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