{"record":{"id":"1633730ef3313770","repo":"hyperledger/fabric","slug":"error-unmarshalling-chaincodeheaderextension-163373","errorCode":null,"errorMessage":"error unmarshalling ChaincodeHeaderExtension","messagePattern":"error unmarshalling ChaincodeHeaderExtension","errorType":"error_code","errorClass":null,"httpStatus":null,"severity":"error","filePath":"protoutil/unmarshalers.go","lineNumber":109,"sourceCode":"// UnmarshalHeader unmarshals bytes to a Header\nfunc UnmarshalHeader(bytes []byte) (*common.Header, error) {\n\thdr := &common.Header{}\n\terr := proto.Unmarshal(bytes, hdr)\n\treturn hdr, errors.Wrap(err, \"error unmarshalling Header\")\n}\n\n// UnmarshalConfigEnvelope unmarshals bytes to a ConfigEnvelope\nfunc UnmarshalConfigEnvelope(bytes []byte) (*common.ConfigEnvelope, error) {\n\tcfg := &common.ConfigEnvelope{}\n\terr := proto.Unmarshal(bytes, cfg)\n\treturn cfg, errors.Wrap(err, \"error unmarshalling ConfigEnvelope\")\n}\n\n// UnmarshalChaincodeHeaderExtension unmarshals bytes to a ChaincodeHeaderExtension\nfunc UnmarshalChaincodeHeaderExtension(hdrExtension []byte) (*peer.ChaincodeHeaderExtension, error) {\n\tchaincodeHdrExt := &peer.ChaincodeHeaderExtension{}\n\terr := proto.Unmarshal(hdrExtension, chaincodeHdrExt)\n\treturn chaincodeHdrExt, errors.Wrap(err, \"error unmarshalling ChaincodeHeaderExtension\")\n}\n\n// UnmarshalProposalResponse unmarshals bytes to a ProposalResponse\nfunc UnmarshalProposalResponse(prBytes []byte) (*peer.ProposalResponse, error) {\n\tproposalResponse := &peer.ProposalResponse{}\n\terr := proto.Unmarshal(prBytes, proposalResponse)\n\treturn proposalResponse, errors.Wrap(err, \"error unmarshalling ProposalResponse\")\n}\n\n// UnmarshalChaincodeAction unmarshals bytes to a ChaincodeAction\nfunc UnmarshalChaincodeAction(caBytes []byte) (*peer.ChaincodeAction, error) {\n\tchaincodeAction := &peer.ChaincodeAction{}\n\terr := proto.Unmarshal(caBytes, chaincodeAction)\n\treturn chaincodeAction, errors.Wrap(err, \"error unmarshalling ChaincodeAction\")\n}\n\n// UnmarshalResponse unmarshals bytes to a Response\nfunc UnmarshalResponse(resBytes []byte) (*peer.Response, error) {","sourceCodeStart":91,"sourceCodeEnd":127,"githubUrl":"https://github.com/hyperledger/fabric/blob/2736b63f8fd5932511d56fe68b7039d15977f7f6/protoutil/unmarshalers.go#L91-L127","documentation":"Returned by protoutil.UnmarshalChaincodeHeaderExtension when proto.Unmarshal fails to decode the header extension bytes into a peer.ChaincodeHeaderExtension. The wrap adds the failing message type to the protobuf error. It means the hdrExtension bytes are not a validly encoded ChaincodeHeaderExtension.","triggerScenarios":"Calling UnmarshalChaincodeHeaderExtension on channel header extensions that are empty, truncated, or belong to a different message type (e.g. config-style extension bytes); reached from getTxCCInstance, proposal validation, and TestProposal paths.","commonSituations":"Processing proposals whose ChannelHeader.Extension was not populated by the SDK; parsing blocks from a different Fabric version where extension semantics changed; hand-built proposals omitting the extension.","solutions":["Verify the proposal's ChannelHeader.Extension is set and marshaled as a ChaincodeHeaderExtension (chaincode_id field).","Check the channel header type is ENDORSER_TRANSACTION before unmarshaling the extension.","Confirm the SDK used to build the transaction matches the peer's Fabric version.","Guard against empty extension bytes and skip/return early when extension is absent.","Log the failing bytes (length + base64) to confirm the wrong message type isn't being passed."],"exampleFix":"// before\next, _ := protoutil.UnmarshalChaincodeHeaderExtension(chdr.Extension) // may be empty\n// after\nif len(chdr.Extension) == 0 {\n    return nil, errors.New(\"missing chaincode header extension\")\n}\next, err := protoutil.UnmarshalChaincodeHeaderExtension(chdr.Extension)\nif err != nil {\n    return nil, fmt.Errorf(\"bad header extension: %w\", err)\n}","handlingStrategy":"validation","validationCode":"func hasHeaderExtension(chdr *common.ChannelHeader) bool {\n    return chdr.Type == int32(common.HeaderType_ENDORSER_TRANSACTION) && len(chdr.Extension) > 0\n}","typeGuard":"func isChaincodeHeaderExtension(v any) bool {\n    ext, ok := v.(*peer.ChaincodeHeaderExtension)\n    return ok && ext.ChaincodeId != nil\n}","tryCatchPattern":"ext, err := protoutil.UnmarshalChaincodeHeaderExtension(chdr.Extension)\nif err != nil {\n    return nil, fmt.Errorf(\"missing/invalid header extension: %w\", err)\n}","preventionTips":["Verify proposals set ChannelHeader.Extension with a marshaled ChaincodeHeaderExtension","Skip gracefully when extension is empty for non-endorser transactions","Keep transaction-building SDK on the same Fabric version as the peer","Log failing extension bytes for support/debugging"],"tags":["fabric","protobuf","unmarshal","proposal","chaincode"],"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"}