hyperledger/fabric · error

error unmarshalling signatures from metadata: %v

Error message

error unmarshalling signatures from metadata: %v

What it means

Within BlockSignatureVerifier, after confirming the SIGNATURES metadata entry exists, its bytes are proto-unmarshalled into cb.Metadata. Failure produces this wrapped error, meaning the signature entry bytes are corrupt or not a valid Metadata message containing Value and Signatures.

Source

Thrown at protoutil/blockutils.go:259

type BlockVerifierFunc func(header *cb.BlockHeader, metadata *cb.BlockMetadata) error

//go:generate counterfeiter -o mocks/policy.go --fake-name Policy . policy
type policy interface { // copied from common.policies to avoid circular import.
	// EvaluateSignedData takes a set of SignedData and evaluates whether
	// 1) the signatures are valid over the related message
	// 2) the signing identities satisfy the policy
	EvaluateSignedData(signatureSet []*SignedData) error
}

func BlockSignatureVerifier(bftEnabled bool, consenters []*cb.Consenter, policy policy) BlockVerifierFunc {
	return func(header *cb.BlockHeader, metadata *cb.BlockMetadata) error {
		if len(metadata.GetMetadata()) < int(cb.BlockMetadataIndex_SIGNATURES)+1 {
			return errors.Errorf("no signatures in block metadata")
		}

		md := &cb.Metadata{}
		if err := proto.Unmarshal(metadata.Metadata[cb.BlockMetadataIndex_SIGNATURES], md); err != nil {
			return errors.Wrapf(err, "error unmarshalling signatures from metadata: %v", err)
		}

		var signatureSet []*SignedData
		for _, metadataSignature := range md.Signatures {
			var signerIdentity []byte
			var signedPayload []byte
			// if the SignatureHeader is empty and the IdentifierHeader is present, then  the consenter expects us to fetch its identity by its numeric identifier
			if bftEnabled && len(metadataSignature.GetSignatureHeader()) == 0 && len(metadataSignature.GetIdentifierHeader()) > 0 {
				identifierHeader, err := UnmarshalIdentifierHeader(metadataSignature.IdentifierHeader)
				if err != nil {
					return fmt.Errorf("failed unmarshalling identifier header for block %d: %v", header.GetNumber(), err)
				}
				identifier := identifierHeader.GetIdentifier()
				signerIdentity = searchConsenterIdentityByID(consenters, identifier)
				if len(signerIdentity) == 0 {
					// The identifier is not within the consenter set
					continue
				}

View on GitHub (pinned to 2736b63f8f)

Solutions

  1. Re-fetch the block from a trusted ordering node
  2. Verify the metadata index actually holds a serialized cb.Metadata (starts with valid protobuf field tags)
  3. If corruption recurs, rebuild the ledger or restore from backup
  4. Ensure all Fabric components run compatible versions so metadata layout matches

Example fix

// before
md := &cb.Metadata{}
if err := proto.Unmarshal(metadata.Metadata[cb.BlockMetadataIndex_SIGNATURES], md); err != nil {
    return errors.Wrapf(err, "error unmarshalling signatures from metadata: %v", err)
}
// after
md := &cb.Metadata{}
raw := metadata.Metadata[cb.BlockMetadataIndex_SIGNATURES]
if err := proto.Unmarshal(raw, md); err != nil {
    return errors.Wrapf(err, "block %d: signatures metadata (%d bytes) is not valid protobuf", header.GetNumber(), len(raw))
}
Defensive patterns

Strategy: validation

Validate before calling

raw := metadata.Metadata[cb.BlockMetadataIndex_SIGNATURES]
probe := &cb.Metadata{}
if len(raw) == 0 || proto.Unmarshal(raw, probe) != nil {
    return errors.New("signature metadata not parseable; re-fetch block")
}

Type guard

func isParseableSignatureMetadata(raw []byte) (*cb.Metadata, bool) {
    m := &cb.Metadata{}
    if len(raw) == 0 || proto.Unmarshal(raw, m) != nil {
        return nil, false
    }
    return m, true
}

Try / catch

if err := verifier(header, metadata); err != nil {
    logger.Warnf("signature metadata unparseable for block %d: %v", header.GetNumber(), err)
    return refetchAndVerify(header.GetNumber())
}

Prevention

When it happens

Trigger: Calling BlockSignatureVerifier's returned func on a block whose Metadata[BlockMetadataIndex_SIGNATURES] bytes fail proto.Unmarshal — corrupt ledger data, wrong index contents, or bytes not produced by the ordering service.

Common situations: Reading blocks from an unreliable peer/gossip path, truncated file-ledger segments, or custom block generators writing raw bytes into the signatures slot.

Understand the failure class

Background: "cannot parse invalid wire-format data", "cannot unmarshal", "failed unmarshalling": protobuf unmarshal errors explained — this error's family across 10 libraries.

Related errors


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