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
- Re-fetch the block from a trusted ordering node and retry verification
- Check that the signature entry genuinely contains a SignatureHeader (not an IdentifierHeader) and that bftEnabled matches the actual consensus type
- Validate header bytes decode cleanly before building the SignedData set
- 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
- Set bftEnabled to match the actual consensus type so the correct decode path runs
- Reject signatures with empty headers before verification
- Re-fetch blocks that fail header parsing rather than retrying locally
- Keep all nodes on compatible Fabric versions
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
- failed unmarshalling identifier header for block %d: %v
- error unmarshalling signatures from metadata: %v
- too few arguments
- Failed opening file %s: %v
- config isn't valid
AI-assisted analysis of hyperledger/fabric@2736b63f8f (2026-09-04).
Data as JSON: /api/errors/c9ad22414b463b69.
Report an issue: GitHub.