hyperledger/fabric · error
malformed signature header
Error message
malformed signature header
What it means
Each consenter signature carries an IdentifierHeader (protobuf) binding the signature to a consenter identity number. VerifyConsenterSig -> verifySignatureIsBoundToProposal unmarshals it and this error means the bytes are not a valid IdentifierHeader — the signature's IdentifierHeader field is empty, truncated, or corrupted.
Source
Thrown at orderer/consensus/smartbft/verifier.go:394
func (v *Verifier) verifySignatureIsBoundToProposal(sig *Signature, identityID uint64, prop types.Proposal) error {
// We verify the following fields:
// ConsenterMetadata []byte
// SignatureHeader []byte
// BlockHeader []byte
// OrdererBlockMetadata []byte
// Ensure block header is equal
if !bytes.Equal(prop.Header, sig.BlockHeader) {
v.Logger.Errorf("Expected block header %s but got %s", base64.StdEncoding.EncodeToString(prop.Header),
base64.StdEncoding.EncodeToString(sig.BlockHeader))
return errors.Errorf("mismatched block header")
}
// Ensure signature header matches the identity
sigHdr := &cb.IdentifierHeader{}
if err := proto.Unmarshal(sig.IdentifierHeader, sigHdr); err != nil {
return errors.Wrap(err, "malformed signature header")
}
if identityID != uint64(sigHdr.Identifier) {
v.Logger.Warnf("Expected identity %d but got %d", identityID,
sigHdr.Identifier)
return errors.Errorf("identity in signature header does not match expected identity")
}
// Ensure orderer block metadata's consenter MD matches the proposal
ordererMD := &cb.OrdererBlockMetadata{}
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")
}View on GitHub (pinned to 2736b63f8f)
Solutions
- Discard the malformed signature and re-request it from the signing consenter.
- Confirm all ordering nodes run the same Fabric version so IdentifierHeader encoding is identical.
- Enable debug logging on the BFT message layer to find where the payload got truncated or corrupted.
- If it follows a restart from persisted state, delete/refresh the corrupted signature metadata (view/sequence data) and re-join the consensus flow.
Example fix
// before: truncated signature payload
sig.IdentifierHeader = []byte{0x0a, 0x05} // invalid proto -> error
// after: valid marshalled IdentifierHeader
sig.IdentifierHeader = protoutil.MarshalOrPanic(&cb.IdentifierHeader{Identifier: uint32(2)}) Defensive patterns
Strategy: type-guard
Validate before calling
if len(sig.IdentifierHeader) == 0 {
return errors.New("signature has empty IdentifierHeader; reject message")
} Type guard
func validIdentifierHeader(b []byte) bool {
h := &cb.IdentifierHeader{}
return len(b) > 0 && proto.Unmarshal(b, h) == nil
} Try / catch
err := verifier.VerifyConsenterSig(sig, id)
if err != nil && strings.Contains(err.Error(), "malformed signature header") {
// discard corrupted signature and re-request from consenter
} Prevention
- Use the same Fabric build across all consenters
- Checksum/sign BFT messages on the wire to detect truncation
- Rebuild consensus state if persisted signature metadata fails to unmarshal after restart
When it happens
Trigger: VerifyConsenterSig -> verifySignatureIsBoundToProposal: proto.Unmarshal(sig.IdentifierHeader, sigHdr) returns an error — sig.IdentifierHeader is nil/empty or contains garbage bytes. Happens when a VerificationData blob is malformed, truncated in transit, or produced by incompatible code.
Common situations: Corrupted BFT message over the network; version skew between nodes producing different signature payloads; a replayed or hand-assembled VerificationData file; storage corruption of persisted signature metadata.
Understand the failure class
- Parsing and encoding errors: unexpected token, malformed input — why parsers reject input and how to find the real culprit.
Related errors
- failed to unmarshal BFT metadata configuration
- failed to marshal request envelope: proto: Marshal called wi
- invalid consensus type property in config: %v
- invalid options encoded in consensus metadata: %v
- bad payload
AI-assisted analysis of hyperledger/fabric@2736b63f8f (2026-09-04).
Data as JSON: /api/errors/2d47543199a54b6f.
Report an issue: GitHub.