hyperledger/fabric · error

failed unmarshaling smartbft metadata from proposal

Error message

failed unmarshaling smartbft metadata from proposal

What it means

The ViewMetadata supplied with the proposal (the raw metadata parameter) must itself decode into smartbftprotos.ViewMetadata. If it cannot be unmarshaled, the proposal's metadata is malformed and the verifier wraps the error, mirroring the block-side failure but attributed to the proposal.

Source

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

	signatureMetadata, err := protoutil.GetMetadataFromBlock(block, cb.BlockMetadataIndex_SIGNATURES)
	if err != nil {
		return nil, err
	}
	ordererMetadataFromSignature := &cb.OrdererBlockMetadata{}
	if err := proto.Unmarshal(signatureMetadata.Value, ordererMetadataFromSignature); err != nil {
		return nil, errors.Wrap(err, "failed unmarshaling OrdererBlockMetadata")
	}

	// Ensure the view metadata in the block signature and in the proposal are the same

	metadataInBlock := &smartbftprotos.ViewMetadata{}
	if err := proto.Unmarshal(ordererMetadataFromSignature.ConsenterMetadata, metadataInBlock); err != nil {
		return nil, errors.Wrap(err, "failed unmarshaling smartbft metadata from block")
	}

	metadataFromProposal := &smartbftprotos.ViewMetadata{}
	if err := proto.Unmarshal(metadata, metadataFromProposal); err != nil {
		return nil, errors.Wrap(err, "failed unmarshaling smartbft metadata from proposal")
	}

	if !proto.Equal(metadataInBlock, metadataFromProposal) {
		return nil, errors.Errorf(
			"expected metadata in block to be [view_id:%d latest_sequence:%d] but got [view_id:%d latest_sequence:%d]",
			metadataFromProposal.GetViewId(), metadataFromProposal.GetLatestSequence(),
			metadataInBlock.GetViewId(), metadataInBlock.GetLatestSequence(),
		)
	}

	rtc := v.RuntimeConfig.Load().(RuntimeConfig)
	lastConfig := rtc.LastConfigBlock.Header.Number

	if protoutil.IsConfigBlock(block) {
		lastConfig = block.Header.Number
	}

	// Verify last config

View on GitHub (pinned to 2736b63f8f)

Solutions

  1. Verify the caller passes the marshaled smartbftprotos.ViewMetadata, not other metadata blobs
  2. Check smartbft library version parity across all consenter nodes
  3. Marshal metadata explicitly with proto.Marshal on the ViewMetadata message before proposal
  4. Log the offending metadata bytes to identify the wrong source

Example fix

// before: passing orderer metadata instead of view metadata
err := verifier.VerifyProposal([]byte{...}, ordererMetadataBytes)
// after
viewMetaBytes, _ := proto.Marshal(viewMetadata)
err := verifier.VerifyProposal([]byte{...}, viewMetaBytes)
Defensive patterns

Strategy: validation

Validate before calling

pm := &smartbftprotos.ViewMetadata{}
if err := proto.Unmarshal(proposalMetadataBytes, pm); err != nil {
    return errors.New("proposal metadata is not a valid ViewMetadata")
}

Type guard

func validProposalMetadata(b []byte) bool { return proto.Unmarshal(b, &smartbftprotos.ViewMetadata{}) == nil }

Try / catch

if _, err := verifier.VerifyProposal(proposal, metadata); err != nil && strings.Contains(err.Error(), "smartbft metadata from proposal") {
    logger.Warn("malformed proposal metadata; verify caller passes marshaled ViewMetadata")
}

Prevention

When it happens

Trigger: VerifyProposal is called with a metadata []byte argument that fails proto.Unmarshal into ViewMetadata — e.g. nil/empty bytes, wrong message type, or bytes from a different smartbft version.

Common situations: Caller passing the wrong byte slice (block bytes or orderer metadata instead of view metadata); version mismatch between the leader producing the proposal and the verifier; corrupted proposal received over the network.

Related errors


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