hyperledger/fabric · error
Block.Metadata is nil or Block.Metadata lacks a Tx filter bi
Error message
Block.Metadata is nil or Block.Metadata lacks a Tx filter bitmap
What it means
getTxPvtdataInfoFromBlock reads the transaction-filter bitmap stored in block.Metadata at index BlockMetadataIndex_TRANSACTIONS_FILTER to determine which txs are valid. If block.Metadata is nil, or the metadata array is too short to contain the filter, the block is considered malformed for private-data purposes and this error is returned.
Source
Thrown at gossip/privdata/coordinator.go:299
if !isAuthorized(peerAuthInfo) {
c.logger.Debugf("Skipping collection criteria [%#v] because peer isn't authorized", cc)
continue
}
seqs2Namespaces.addCollection(uint64(seqInBlock), txPvtDataItem.WriteSet.DataModel, ns.Namespace, col)
}
}
}
return blockAndPvtData.Block, seqs2Namespaces.asPrivateData(), nil
}
// getTxPvtdataInfoFromBlock parses the block transactions and returns the list of private data items in the block.
// Note that this peer's eligibility for the private data is not checked here.
func (c *coordinator) getTxPvtdataInfoFromBlock(block *common.Block) ([]*ledger.TxPvtdataInfo, error) {
txPvtdataItemsFromBlock := []*ledger.TxPvtdataInfo{}
if block.Metadata == nil || len(block.Metadata.Metadata) <= int(common.BlockMetadataIndex_TRANSACTIONS_FILTER) {
return nil, errors.New("Block.Metadata is nil or Block.Metadata lacks a Tx filter bitmap")
}
txsFilter := txValidationFlags(block.Metadata.Metadata[common.BlockMetadataIndex_TRANSACTIONS_FILTER])
data := block.Data.Data
if len(txsFilter) != len(block.Data.Data) {
return nil, errors.Errorf("block data size(%d) is different from Tx filter size(%d)", len(block.Data.Data), len(txsFilter))
}
for seqInBlock, txEnvBytes := range data {
invalid := txsFilter[seqInBlock] != uint8(peer.TxValidationCode_VALID)
txInfo, err := getTxInfoFromTransactionBytes(txEnvBytes)
if err != nil {
continue
}
colPvtdataInfo := []*ledger.CollectionPvtdataInfo{}
for _, ns := range txInfo.txRWSet.NsRwSets {
for _, hashedCollection := range ns.CollHashedRwSets {
// skip if no writesView on GitHub (pinned to 2736b63f8f)
Solutions
- Use a full block produced by the ordering service including all standard metadata entries
- Regenerate/repair the block with proper Metadata (esp. the TRANSACTIONS_FILTER entry)
- Update tooling/versions so block generation matches the fabric proto expectations
- In tests, populate block.Metadata.Metadata[common.BlockMetadataIndex_TRANSACTIONS_FILTER]
Example fix
// before
blk := &common.Block{Header: h, Data: d}
c.StoreBlock(blk, nil)
// after
blk.Metadata = &common.BlockMetadata{
Metadata: make([][]byte, int(common.BlockMetadataIndex_TRANSACTIONS_FILTER)+1),
}
blk.Metadata.Metadata[common.BlockMetadataIndex_TRANSACTIONS_FILTER] =
bytes.Repeat([]byte{byte(peer.TxValidationCode_VALID)}, len(d.Data))
c.StoreBlock(blk, nil) Defensive patterns
Strategy: validation
Validate before calling
func blockHasTxFilter(b *common.Block) bool {
return b.Metadata != nil &&
len(b.Metadata.Metadata) > int(common.BlockMetadataIndex_TRANSACTIONS_FILTER)
}
if !blockHasTxFilter(block) {
return errors.New("block lacks Tx filter metadata")
} Type guard
func hasTxFilterMetadata(b *common.Block) bool {
return b != nil && b.Metadata != nil &&
len(b.Metadata.Metadata) > int(common.BlockMetadataIndex_TRANSACTIONS_FILTER) &&
len(b.Metadata.Metadata[common.BlockMetadataIndex_TRANSACTIONS_FILTER]) > 0
} Prevention
- Always build blocks with the full standard metadata array in tests/tools
- Keep block-producing tooling aligned with the fabric proto version
- Reject blocks lacking metadata at ingestion, before StoreBlock
- Never strip Metadata when exporting/importing blocks
When it happens
Trigger: StoreBlock -> getTxPvtdataInfoFromBlock called with a block whose Metadata is nil or whose Metadata.Metadata slice has length <= BlockMetadataIndex_TRANSACTIONS_FILTER (index 2).
Common situations: Blocks produced by non-Fabric tooling or older/different fabric versions lacking the Tx filter metadata; hand-crafted test blocks without Metadata; corrupted blocks fetched from a misbehaving source.
Related errors
- block data size(%d) is different from Tx filter size(%d)
- Block data is empty
- Block header is nil
- message isn't an alive message
- message isn't a stateInfo message
AI-assisted analysis of hyperledger/fabric@2736b63f8f (2026-09-04).
Data as JSON: /api/errors/8308150534e30929.
Report an issue: GitHub.