hyperledger/fabric · error

block metadata is of size %d but should be of size %d

Error message

block metadata is of size %d but should be of size %d

What it means

A Fabric block's Metadata.Metadata slice must contain one entry per indexed metadata type (SIGNATURES, LAST_CONFIG, TRANSACTIONS_FILTER, ORDERER — i.e. len(cb.BlockMetadataIndex_name)). VerifyConsenterSig -> verifySignatureIsBoundToProposal checks this right after converting the proposal to a block; this error means the block derived from the proposal is missing (or has extra) metadata slots, so indexed entries like signatures or last-config cannot be located safely.

Source

Thrown at orderer/consensus/smartbft/verifier.go:422

	if err := proto.Unmarshal(sig.OrdererBlockMetadata, ordererMD); err != nil {
		return errors.Wrap(err, "malformed orderer metadata in signature")
	}

	if !bytes.Equal(ordererMD.ConsenterMetadata, prop.Metadata) {
		v.Logger.Warnf("Expected consenter metadata %s but got %s in proposal",
			base64.StdEncoding.EncodeToString(ordererMD.ConsenterMetadata), base64.StdEncoding.EncodeToString(prop.Metadata))
		return errors.Errorf("consenter metadata in OrdererBlockMetadata doesn't match proposal")
	}

	block, err := ProposalToBlock(prop)
	if err != nil {
		v.Logger.Warnf("got malformed proposal: %v", err)
		return err
	}

	// Ensure Metadata slice is of the right size
	if len(block.Metadata.Metadata) != len(cb.BlockMetadataIndex_name) {
		return errors.Errorf("block metadata is of size %d but should be of size %d",
			len(block.Metadata.Metadata), len(cb.BlockMetadataIndex_name))
	}

	signatureMetadata := &cb.Metadata{}
	if err := proto.Unmarshal(block.Metadata.Metadata[cb.BlockMetadataIndex_SIGNATURES], signatureMetadata); err != nil {
		return errors.Wrap(err, "malformed signature metadata")
	}

	ordererMDFromBlock := &cb.OrdererBlockMetadata{}
	if err := proto.Unmarshal(signatureMetadata.Value, ordererMDFromBlock); err != nil {
		return errors.Wrap(err, "malformed orderer metadata in block")
	}

	// Ensure the block's OrdererBlockMetadata matches the signature.
	if !proto.Equal(ordererMDFromBlock, ordererMD) {
		return errors.Errorf("signature's OrdererBlockMetadata and OrdererBlockMetadata extracted from block do not match")
	}

View on GitHub (pinned to 2736b63f8f)

Solutions

  1. Upgrade all ordering nodes to the same Fabric version so blocks always carry all metadata indexes.
  2. Ensure the channel uses the SmartBFT consenters path to build blocks (Raft/BFT plugin mismatch produces wrong metadata layout).
  3. Reject the proposal and force a view change so a correctly built block is proposed.
  4. Check any custom tooling that constructs blocks and make it populate Metadata.Metadata for every entry in cb.BlockMetadataIndex_name.

Example fix

// before: block with only 3 metadata slots
block.Metadata.Metadata = []([]byte){sigs, lastConf, txFilter} // -> error
// after: include ORDERER metadata slot (index 3)
block.Metadata.Metadata = append(block.Metadata.Metadata, ordererMDBytes) // length == len(BlockMetadataIndex_name)
Defensive patterns

Strategy: validation

Validate before calling

if len(block.Metadata.GetMetadata()) != len(cb.BlockMetadataIndex_name) {
    return fmt.Errorf("block has %d metadata slots, need %d",
        len(block.Metadata.GetMetadata()), len(cb.BlockMetadataIndex_name))
}

Try / catch

if err := verifyProposal(prop); err != nil {
    if strings.Contains(err.Error(), "block metadata is of size") {
        // upgrade/fix block producer, force view change
    }
    return err
}

Prevention

When it happens

Trigger: VerifyConsenterSig -> verifySignatureIsBoundToProposal: len(block.Metadata.Metadata) != len(cb.BlockMetadataIndex_name). Happens when the proposal was built with fewer metadata entries than the current protocol expects — e.g. missing the ORDERER (index 3) entry that SmartBFT requires.

Common situations: Fabric version skew: pre-SmartBFT / older encoding with 3 metadata slots vs. 4 required; a custom block builder that doesn't populate all metadata indexes; corrupted proposal metadata; blocks produced by a non-SmartBFT consensus plugin mixed into a SmartBFT channel.

Related errors


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