hyperledger/fabric · error
block with id [%d] on channel [%s] does not have metadata or
Error message
block with id [%d] on channel [%s] does not have metadata or contains too few entries
What it means
verifyMetadata ensures a delivered block carries block.Metadata with entries for every registered BlockMetadataIndex (SIGNATURES, LAST_CONFIG, TRANSACTIONS_FILTER, ORDERER). A nil Metadata or too-few entries means signature/metadata validation is impossible, so the block is rejected.
Source
Thrown at common/deliverclient/block_verification.go:305
err := a.sigVerifierFunc(block.Header, block.Metadata)
if err == nil {
a.lastBlockHeader = block.Header
a.lastBlockHeaderHash = protoutil.BlockHeaderHash(block.Header)
}
return err
}
// UpdateBlockHeader saves the last block header that was verified and handled successfully.
// This must be called after VerifyBlock and VerifyBlockAttestation and successfully handling the block.
func (a *BlockVerificationAssistant) UpdateBlockHeader(block *common.Block) {
a.lastBlockHeader = block.Header
a.lastBlockHeaderHash = protoutil.BlockHeaderHash(block.Header)
}
func (a *BlockVerificationAssistant) verifyMetadata(block *common.Block) error {
if block.Metadata == nil || len(block.Metadata.Metadata) < len(common.BlockMetadataIndex_name) {
return errors.Errorf("block with id [%d] on channel [%s] does not have metadata or contains too few entries", block.Header.Number, a.channelID)
}
return nil
}
func (a *BlockVerificationAssistant) verifyHeader(block *common.Block) error {
if block == nil {
return errors.Errorf("block must be different from nil, channel=%s", a.channelID)
}
if block.Header == nil {
return errors.Errorf("invalid block, header must be different from nil, channel=%s", a.channelID)
}
expectedBlockNum := a.lastBlockHeader.Number + 1
if expectedBlockNum != block.Header.Number {
return errors.Errorf("expected block number is [%d] but actual block number inside block is [%d]", expectedBlockNum, block.Header.Number)
}
View on GitHub (pinned to 2736b63f8f)
Solutions
- Ensure the block source is a real orderer-produced block containing full Metadata (signature metadata, last-config pointer, tx filter).
- Re-fetch the block from a healthy orderer/peer.
- Upgrade/align fabric component versions so metadata layouts match.
- If generating blocks for tests, populate Metadata with len(common.BlockMetadataIndex_name) entries.
Example fix
// before
block := &common.Block{Header: hdr, Data: data} // Metadata nil
// after
block := &common.Block{Header: hdr, Data: data, Metadata: &common.BlockMetadata{Metadata: [][]byte{sigMeta, lastConfig, txFilter, ordererMeta}}} Defensive patterns
Strategy: validation
Validate before calling
if block.Metadata == nil || len(block.Metadata.Metadata) < len(common.BlockMetadataIndex_name) {
return errors.New("block metadata incomplete; refetch from orderer")
} Type guard
func hasFullMetadata(block *common.Block) bool {
return block != nil && block.Metadata != nil && len(block.Metadata.Metadata) >= len(common.BlockMetadataIndex_name)
} Try / catch
if err := bva.VerifyBlock(block, opts); err != nil {
if strings.Contains(err.Error(), "does not have metadata") {
block, err = refetchBlock(block.Header.Number)
}
return err
} Prevention
- Use real orderer-produced blocks; don't hand-assemble blocks for tooling without Metadata
- Align fabric versions across components (metadata layout changes between versions)
- Validate persisted blocks after storage restores/migrations
When it happens
Trigger: VerifyBlock or VerifyBlockAttestation receives a block constructed without Metadata (hand-built blocks in tooling/tests), a block produced by an incompatible orderer writing fewer metadata entries, or a block truncated during storage/transfer so Metadata is missing.
Common situations: Custom block generators for tests omitting Metadata; delivering pre-fabric-1.4-style blocks; corrupted block files; cross-version fabric components with differing metadata layouts.
Related errors
- last block header hash is missing
- failed to verify transactions are well formed for block with
- Header.DataHash is different from Hash(block.Data) for block
- failed to initialize block verifier function
- malformed org definition for org: %s
AI-assisted analysis of hyperledger/fabric@2736b63f8f (2026-09-04).
Data as JSON: /api/errors/3acff828420c454a.
Report an issue: GitHub.