hyperledger/fabric · error

failed unmarshalling signature header for block %d: %v

Error message

failed unmarshalling signature header for block %d: %v

What it means

In the non-BFT (or legacy signature) path of BlockSignatureVerifier, each metadata signature's SignatureHeader is unmarshalled to extract the creator identity. This error indicates the SignatureHeader bytes are corrupt or not a valid SignatureHeader protobuf, so signature verification cannot proceed.

Source

Thrown at protoutil/blockutils.go:282

			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
				}
				signedPayload = util.ConcatenateBytes(md.Value, metadataSignature.IdentifierHeader, BlockHeaderBytes(header))
			} else {
				signatureHeader, err := UnmarshalSignatureHeader(metadataSignature.GetSignatureHeader())
				if err != nil {
					return fmt.Errorf("failed unmarshalling signature header for block %d: %v", header.GetNumber(), err)
				}

				signedPayload = util.ConcatenateBytes(md.Value, metadataSignature.SignatureHeader, BlockHeaderBytes(header))

				signerIdentity = signatureHeader.Creator
			}

			signatureSet = append(
				signatureSet,
				&SignedData{
					Identity:  signerIdentity,
					Data:      signedPayload,
					Signature: metadataSignature.Signature,
				},
			)
		}

		return policy.EvaluateSignedData(signatureSet)

View on GitHub (pinned to 2736b63f8f)

Solutions

  1. Re-fetch the block from a trusted ordering node and retry verification
  2. Check that the signature entry genuinely contains a SignatureHeader (not an IdentifierHeader) and that bftEnabled matches the actual consensus type
  3. Validate header bytes decode cleanly before building the SignedData set
  4. Rebuild/restore the ledger if multiple blocks fail the same way

Example fix

// before
signatureHeader, err := UnmarshalSignatureHeader(metadataSignature.GetSignatureHeader())
if err != nil {
    return fmt.Errorf("failed unmarshalling signature header for block %d: %v", header.GetNumber(), err)
}
// after
if len(metadataSignature.GetSignatureHeader()) == 0 {
    return fmt.Errorf("block %d: signature has empty signature header", header.GetNumber())
}
signatureHeader, err := UnmarshalSignatureHeader(metadataSignature.GetSignatureHeader())
if err != nil {
    return fmt.Errorf("failed unmarshalling signature header for block %d: %v", header.GetNumber(), err)
}
Defensive patterns

Strategy: validation

Validate before calling

for _, s := range md.Signatures {
    if bftEnabled && len(s.GetIdentifierHeader()) > 0 {
        continue
    }
    sh := &cb.SignatureHeader{} // probe parse
    if len(s.GetSignatureHeader()) == 0 || proto.Unmarshal(s.GetSignatureHeader(), sh) != nil {
        return errors.New("malformed signature header; reject block")
    }
}

Type guard

func isParseableSignatureHeader(raw []byte) bool {
    sh := &cb.SignatureHeader{}
    return len(raw) > 0 && proto.Unmarshal(raw, sh) == nil
}

Try / catch

if err := verifier(header, metadata); err != nil {
    return fmt.Errorf("block %d failed signature verification: %w", header.GetNumber(), err)
}

Prevention

When it happens

Trigger: Calling the BlockSignatureVerifier func on a block whose metadata signatures contain SignatureHeader bytes that fail UnmarshalSignatureHeader — corrupt data, or bytes produced by incompatible code.

Common situations: Standard (Raft/Solo) ordering blocks corrupted in transit or on disk, mismatched Fabric versions altering SignatureHeader contents, or hand-built test blocks with invalid header bytes.

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/c9ad22414b463b69. Report an issue: GitHub.