{"record":{"id":"33382d308987d375","repo":"hyperledger/fabric","slug":"error-unmarshalling-signatures-from-metadata-v","errorCode":null,"errorMessage":"error unmarshalling signatures from metadata: %v","messagePattern":"error unmarshalling signatures from metadata: (.+?)","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"protoutil/blockutils.go","lineNumber":259,"sourceCode":"type BlockVerifierFunc func(header *cb.BlockHeader, metadata *cb.BlockMetadata) error\n\n//go:generate counterfeiter -o mocks/policy.go --fake-name Policy . policy\ntype policy interface { // copied from common.policies to avoid circular import.\n\t// EvaluateSignedData takes a set of SignedData and evaluates whether\n\t// 1) the signatures are valid over the related message\n\t// 2) the signing identities satisfy the policy\n\tEvaluateSignedData(signatureSet []*SignedData) error\n}\n\nfunc BlockSignatureVerifier(bftEnabled bool, consenters []*cb.Consenter, policy policy) BlockVerifierFunc {\n\treturn func(header *cb.BlockHeader, metadata *cb.BlockMetadata) error {\n\t\tif len(metadata.GetMetadata()) < int(cb.BlockMetadataIndex_SIGNATURES)+1 {\n\t\t\treturn errors.Errorf(\"no signatures in block metadata\")\n\t\t}\n\n\t\tmd := &cb.Metadata{}\n\t\tif err := proto.Unmarshal(metadata.Metadata[cb.BlockMetadataIndex_SIGNATURES], md); err != nil {\n\t\t\treturn errors.Wrapf(err, \"error unmarshalling signatures from metadata: %v\", err)\n\t\t}\n\n\t\tvar signatureSet []*SignedData\n\t\tfor _, metadataSignature := range md.Signatures {\n\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}","sourceCodeStart":241,"sourceCodeEnd":277,"githubUrl":"https://github.com/hyperledger/fabric/blob/2736b63f8fd5932511d56fe68b7039d15977f7f6/protoutil/blockutils.go#L241-L277","documentation":"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.","triggerScenarios":"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.","commonSituations":"Reading blocks from an unreliable peer/gossip path, truncated file-ledger segments, or custom block generators writing raw bytes into the signatures slot.","solutions":["Re-fetch the block from a trusted ordering node","Verify the metadata index actually holds a serialized cb.Metadata (starts with valid protobuf field tags)","If corruption recurs, rebuild the ledger or restore from backup","Ensure all Fabric components run compatible versions so metadata layout matches"],"exampleFix":"// before\nmd := &cb.Metadata{}\nif err := proto.Unmarshal(metadata.Metadata[cb.BlockMetadataIndex_SIGNATURES], md); err != nil {\n    return errors.Wrapf(err, \"error unmarshalling signatures from metadata: %v\", err)\n}\n// after\nmd := &cb.Metadata{}\nraw := metadata.Metadata[cb.BlockMetadataIndex_SIGNATURES]\nif err := proto.Unmarshal(raw, md); err != nil {\n    return errors.Wrapf(err, \"block %d: signatures metadata (%d bytes) is not valid protobuf\", header.GetNumber(), len(raw))\n}","handlingStrategy":"validation","validationCode":"raw := metadata.Metadata[cb.BlockMetadataIndex_SIGNATURES]\nprobe := &cb.Metadata{}\nif len(raw) == 0 || proto.Unmarshal(raw, probe) != nil {\n    return errors.New(\"signature metadata not parseable; re-fetch block\")\n}","typeGuard":"func isParseableSignatureMetadata(raw []byte) (*cb.Metadata, bool) {\n    m := &cb.Metadata{}\n    if len(raw) == 0 || proto.Unmarshal(raw, m) != nil {\n        return nil, false\n    }\n    return m, true\n}","tryCatchPattern":"if err := verifier(header, metadata); err != nil {\n    logger.Warnf(\"signature metadata unparseable for block %d: %v\", header.GetNumber(), err)\n    return refetchAndVerify(header.GetNumber())\n}","preventionTips":["Detect recurring failures as signs of ledger/gossip corruption","Verify metadata indices against the producing Fabric version","Re-fetch blocks from trusted orderers before retrying verification","Keep block payloads intact during transport (checksum on delivery)"],"tags":["protobuf","unmarshal","signatures","block-verification"],"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"}