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
- Guard callers with if block.Metadata == nil before calling, or use GetMetadataFromBlockOrPanic only where nil is impossible
- Ensure blocks always come from protoutil/ledger write paths that populate metadata (commitBlock with WriteBlock)
- Regenerate or re-fetch the block if the ledger is corrupt
- 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
- Produce blocks only via ledger/protoutil write paths that always populate Metadata
- Fix test builders to include Metadata with SIGNATURES, LAST_CONFIG, ORDERER entries
- Treat nil-metadata blocks as invalid at ingestion time
- Guard all direct field access with nil checks before helper calls
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
- failed to retrieve channel id - block is empty
- no metadata at index [%s]
- error unmarshalling metadata at index [%s]
- BlockDataHashStructure width only supported at MaxUint32 in
- application config does not exist for %s
AI-assisted analysis of hyperledger/fabric@2736b63f8f (2026-09-04).
Data as JSON: /api/errors/3a8928edce15071e.
Report an issue: GitHub.