{"record":{"id":"c9ad22414b463b69","repo":"hyperledger/fabric","slug":"failed-unmarshalling-signature-header-for-block-d","errorCode":null,"errorMessage":"failed unmarshalling signature header for block %d: %v","messagePattern":"failed unmarshalling signature header for block (.+?): (.+?)","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"protoutil/blockutils.go","lineNumber":282,"sourceCode":"\t\t\tvar signerIdentity []byte\n\t\t\tvar signedPayload []byte\n\t\t\t// if the SignatureHeader is empty and the IdentifierHeader is present, then  the consenter expects us to fetch its identity by its numeric identifier\n\t\t\tif bftEnabled && len(metadataSignature.GetSignatureHeader()) == 0 && len(metadataSignature.GetIdentifierHeader()) > 0 {\n\t\t\t\tidentifierHeader, err := UnmarshalIdentifierHeader(metadataSignature.IdentifierHeader)\n\t\t\t\tif err != nil {\n\t\t\t\t\treturn fmt.Errorf(\"failed unmarshalling identifier header for block %d: %v\", header.GetNumber(), err)\n\t\t\t\t}\n\t\t\t\tidentifier := identifierHeader.GetIdentifier()\n\t\t\t\tsignerIdentity = searchConsenterIdentityByID(consenters, identifier)\n\t\t\t\tif len(signerIdentity) == 0 {\n\t\t\t\t\t// The identifier is not within the consenter set\n\t\t\t\t\tcontinue\n\t\t\t\t}\n\t\t\t\tsignedPayload = util.ConcatenateBytes(md.Value, metadataSignature.IdentifierHeader, BlockHeaderBytes(header))\n\t\t\t} else {\n\t\t\t\tsignatureHeader, err := UnmarshalSignatureHeader(metadataSignature.GetSignatureHeader())\n\t\t\t\tif err != nil {\n\t\t\t\t\treturn fmt.Errorf(\"failed unmarshalling signature header for block %d: %v\", header.GetNumber(), err)\n\t\t\t\t}\n\n\t\t\t\tsignedPayload = util.ConcatenateBytes(md.Value, metadataSignature.SignatureHeader, BlockHeaderBytes(header))\n\n\t\t\t\tsignerIdentity = signatureHeader.Creator\n\t\t\t}\n\n\t\t\tsignatureSet = append(\n\t\t\t\tsignatureSet,\n\t\t\t\t&SignedData{\n\t\t\t\t\tIdentity:  signerIdentity,\n\t\t\t\t\tData:      signedPayload,\n\t\t\t\t\tSignature: metadataSignature.Signature,\n\t\t\t\t},\n\t\t\t)\n\t\t}\n\n\t\treturn policy.EvaluateSignedData(signatureSet)","sourceCodeStart":264,"sourceCodeEnd":300,"githubUrl":"https://github.com/hyperledger/fabric/blob/2736b63f8fd5932511d56fe68b7039d15977f7f6/protoutil/blockutils.go#L264-L300","documentation":"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.","triggerScenarios":"Calling the BlockSignatureVerifier func on a block whose metadata signatures contain SignatureHeader bytes that fail UnmarshalSignatureHeader — corrupt data, or bytes produced by incompatible code.","commonSituations":"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.","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"],"exampleFix":"// before\nsignatureHeader, err := UnmarshalSignatureHeader(metadataSignature.GetSignatureHeader())\nif err != nil {\n    return fmt.Errorf(\"failed unmarshalling signature header for block %d: %v\", header.GetNumber(), err)\n}\n// after\nif len(metadataSignature.GetSignatureHeader()) == 0 {\n    return fmt.Errorf(\"block %d: signature has empty signature header\", header.GetNumber())\n}\nsignatureHeader, err := UnmarshalSignatureHeader(metadataSignature.GetSignatureHeader())\nif err != nil {\n    return fmt.Errorf(\"failed unmarshalling signature header for block %d: %v\", header.GetNumber(), err)\n}","handlingStrategy":"validation","validationCode":"for _, s := range md.Signatures {\n    if bftEnabled && len(s.GetIdentifierHeader()) > 0 {\n        continue\n    }\n    sh := &cb.SignatureHeader{} // probe parse\n    if len(s.GetSignatureHeader()) == 0 || proto.Unmarshal(s.GetSignatureHeader(), sh) != nil {\n        return errors.New(\"malformed signature header; reject block\")\n    }\n}","typeGuard":"func isParseableSignatureHeader(raw []byte) bool {\n    sh := &cb.SignatureHeader{}\n    return len(raw) > 0 && proto.Unmarshal(raw, sh) == nil\n}","tryCatchPattern":"if err := verifier(header, metadata); err != nil {\n    return fmt.Errorf(\"block %d failed signature verification: %w\", header.GetNumber(), err)\n}","preventionTips":["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"],"tags":["signature-header","unmarshal","block-verification","bft"],"backgroundTag":"protobuf-unmarshal-failed","analyzedSha":"2736b63f8fd5932511d56fe68b7039d15977f7f6","analyzedAt":"2026-09-04T08:52:36.465Z","contentChangedAt":"2026-09-04T08:52:36.465Z","schemaVersion":2},"datasetVersion":"2026-09-08T10:18:20.063Z"}