{"record":{"id":"6a7ae5bbc47df551","repo":"hyperledger/fabric","slug":"failed-unmarshaling-smartbft-metadata-from-proposa","errorCode":null,"errorMessage":"failed unmarshaling smartbft metadata from proposal","messagePattern":"failed unmarshaling smartbft metadata from proposal","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"orderer/consensus/smartbft/verifier.go","lineNumber":291,"sourceCode":"\tsignatureMetadata, err := protoutil.GetMetadataFromBlock(block, cb.BlockMetadataIndex_SIGNATURES)\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\tordererMetadataFromSignature := &cb.OrdererBlockMetadata{}\n\tif err := proto.Unmarshal(signatureMetadata.Value, ordererMetadataFromSignature); err != nil {\n\t\treturn nil, errors.Wrap(err, \"failed unmarshaling OrdererBlockMetadata\")\n\t}\n\n\t// Ensure the view metadata in the block signature and in the proposal are the same\n\n\tmetadataInBlock := &smartbftprotos.ViewMetadata{}\n\tif err := proto.Unmarshal(ordererMetadataFromSignature.ConsenterMetadata, metadataInBlock); err != nil {\n\t\treturn nil, errors.Wrap(err, \"failed unmarshaling smartbft metadata from block\")\n\t}\n\n\tmetadataFromProposal := &smartbftprotos.ViewMetadata{}\n\tif err := proto.Unmarshal(metadata, metadataFromProposal); err != nil {\n\t\treturn nil, errors.Wrap(err, \"failed unmarshaling smartbft metadata from proposal\")\n\t}\n\n\tif !proto.Equal(metadataInBlock, metadataFromProposal) {\n\t\treturn nil, errors.Errorf(\n\t\t\t\"expected metadata in block to be [view_id:%d latest_sequence:%d] but got [view_id:%d latest_sequence:%d]\",\n\t\t\tmetadataFromProposal.GetViewId(), metadataFromProposal.GetLatestSequence(),\n\t\t\tmetadataInBlock.GetViewId(), metadataInBlock.GetLatestSequence(),\n\t\t)\n\t}\n\n\trtc := v.RuntimeConfig.Load().(RuntimeConfig)\n\tlastConfig := rtc.LastConfigBlock.Header.Number\n\n\tif protoutil.IsConfigBlock(block) {\n\t\tlastConfig = block.Header.Number\n\t}\n\n\t// Verify last config","sourceCodeStart":273,"sourceCodeEnd":309,"githubUrl":"https://github.com/hyperledger/fabric/blob/2736b63f8fd5932511d56fe68b7039d15977f7f6/orderer/consensus/smartbft/verifier.go#L273-L309","documentation":"The ViewMetadata supplied with the proposal (the raw metadata parameter) must itself decode into smartbftprotos.ViewMetadata. If it cannot be unmarshaled, the proposal's metadata is malformed and the verifier wraps the error, mirroring the block-side failure but attributed to the proposal.","triggerScenarios":"VerifyProposal is called with a metadata []byte argument that fails proto.Unmarshal into ViewMetadata — e.g. nil/empty bytes, wrong message type, or bytes from a different smartbft version.","commonSituations":"Caller passing the wrong byte slice (block bytes or orderer metadata instead of view metadata); version mismatch between the leader producing the proposal and the verifier; corrupted proposal received over the network.","solutions":["Verify the caller passes the marshaled smartbftprotos.ViewMetadata, not other metadata blobs","Check smartbft library version parity across all consenter nodes","Marshal metadata explicitly with proto.Marshal on the ViewMetadata message before proposal","Log the offending metadata bytes to identify the wrong source"],"exampleFix":"// before: passing orderer metadata instead of view metadata\nerr := verifier.VerifyProposal([]byte{...}, ordererMetadataBytes)\n// after\nviewMetaBytes, _ := proto.Marshal(viewMetadata)\nerr := verifier.VerifyProposal([]byte{...}, viewMetaBytes)","handlingStrategy":"validation","validationCode":"pm := &smartbftprotos.ViewMetadata{}\nif err := proto.Unmarshal(proposalMetadataBytes, pm); err != nil {\n    return errors.New(\"proposal metadata is not a valid ViewMetadata\")\n}","typeGuard":"func validProposalMetadata(b []byte) bool { return proto.Unmarshal(b, &smartbftprotos.ViewMetadata{}) == nil }","tryCatchPattern":"if _, err := verifier.VerifyProposal(proposal, metadata); err != nil && strings.Contains(err.Error(), \"smartbft metadata from proposal\") {\n    logger.Warn(\"malformed proposal metadata; verify caller passes marshaled ViewMetadata\")\n}","preventionTips":["Pass proto.Marshal(viewMetadata) output as the metadata argument, never other blobs","Unit-test VerifyProposal calls with known-good metadata bytes","Keep smartbft library versions in lockstep across the cluster","Log metadata bytes on failure to confirm the correct source slice"],"tags":["smartbft","fabric","protobuf","view-metadata"],"backgroundTag":"metadata-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"}