{"record":{"id":"aa8471593a59bcb3","repo":"hyperledger/fabric","slug":"proto-marshal-called-with-nil-aa8471","errorCode":null,"errorMessage":"proto: Marshal called with nil","messagePattern":"proto: Marshal called with nil","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"protoutil/proputils.go","lineNumber":348,"sourceCode":"\tvscc []byte,\n\tcollectionConfig []byte,\n) (*peer.Proposal, string, error) {\n\tif collectionConfig == nil {\n\t\treturn createProposalFromCDS(channelID, cds, creator, \"upgrade\", policy, escc, vscc)\n\t}\n\treturn createProposalFromCDS(channelID, cds, creator, \"upgrade\", policy, escc, vscc, collectionConfig)\n}\n\n// createProposalFromCDS returns a deploy or upgrade proposal given a\n// serialized identity and a ChaincodeDeploymentSpec\nfunc createProposalFromCDS(channelID string, msg proto.Message, creator []byte, propType string, args ...[]byte) (*peer.Proposal, string, error) {\n\t// in the new mode, cds will be nil, \"deploy\" and \"upgrade\" are instantiates.\n\tvar ccinp *peer.ChaincodeInput\n\tvar b []byte\n\tvar err error\n\tif msg != nil {\n\t\tif !msg.ProtoReflect().IsValid() {\n\t\t\treturn nil, \"\", errors.New(\"proto: Marshal called with nil\")\n\t\t}\n\t\tb, err = proto.Marshal(msg)\n\t\tif err != nil {\n\t\t\treturn nil, \"\", err\n\t\t}\n\t}\n\tswitch propType {\n\tcase \"deploy\":\n\t\tfallthrough\n\tcase \"upgrade\":\n\t\tcds, ok := msg.(*peer.ChaincodeDeploymentSpec)\n\t\tif !ok || cds == nil {\n\t\t\treturn nil, \"\", errors.New(\"invalid message for creating lifecycle chaincode proposal\")\n\t\t}\n\t\tArgs := [][]byte{[]byte(propType), []byte(channelID), b}\n\t\tArgs = append(Args, args...)\n\n\t\tccinp = &peer.ChaincodeInput{Args: Args}","sourceCodeStart":330,"sourceCodeEnd":366,"githubUrl":"https://github.com/hyperledger/fabric/blob/2736b63f8fd5932511d56fe68b7039d15977f7f6/protoutil/proputils.go#L330-L366","documentation":"createProposalFromCDS (used by CreateInstallProposalFromCDS, CreateDeployProposalFromCDS, CreateUpgradeProposalFromCDS) pre-checks msg with ProtoReflect().IsValid() and returns 'proto: Marshal called with nil' before invoking proto.Marshal. It guards against nil or invalid protobuf messages being embedded as chaincode input bytes in the proposal.","triggerScenarios":"Passing a nil msg, or a nil-pointer protobuf message (invalid ProtoReflect state), as the ChaincodeInput/deployment message when building install/deploy/upgrade proposals — e.g. cds.Input never set or a zero-valued pointer typed field.","commonSituations":"CLI/SDK chaincode install and upgrade flows after a protobuf API migration (github.com/golang/protobuf to google.golang.org/protobuf), where constructing ChaincodeInput changed and left the message nil.","solutions":["Ensure the ChaincodeInput (cds.Input) is non-nil and populated with Args before calling Create*ProposalFromCDS","Use proto.Clone/creation helpers that return valid messages; avoid passing typed nil pointers","Validate with msg.ProtoReflect().IsValid() (or msg != nil for legacy API) at the call site before building the proposal"],"exampleFix":"// before\ninv, err := protoutil.CreateInstallProposalFromCDS(nil cds, creator) // cds.Input nil\n// after\nif cds.Input == nil {\n\tcds.Input = &peer.ChaincodeInput{Args: [][]byte{[]byte(\"install\")}}\n}\ninv, err := protoutil.CreateInstallProposalFromCDS(cds, creator)","handlingStrategy":"type-guard","validationCode":"func validCDS(cds *peer.ChaincodeDeploymentSpec) error {\n\tif cds == nil || cds.ChaincodeSpec == nil || cds.ChaincodeSpec.ChaincodeId == nil {\n\t\treturn errors.New(\"CDS incomplete\")\n\t}\n\tif cds.Input == nil {\n\t\treturn errors.New(\"CDS Input (ChaincodeInput) is nil\")\n\t}\n\treturn nil\n}","typeGuard":"func isMarshalable(m proto.Message) bool {\n\treturn m != nil && m.ProtoReflect().IsValid()\n}","tryCatchPattern":"prop, _, err := protoutil.CreateInstallProposalFromCDS(cds, creator)\nif err != nil {\n\tif strings.Contains(err.Error(), \"Marshal called with nil\") {\n\t\treturn nil, fmt.Errorf(\"chaincode input message not initialized: %w\", err)\n\t}\n\treturn nil, err\n}","preventionTips":["Always populate cds.Input with Args before building install/deploy/upgrade proposals","After protobuf API migrations, check message validity with ProtoReflect().IsValid()","Nil-check typed pointer fields (ChaincodeSpec, ChaincodeId, Input) before proposal creation"],"tags":["hyperledger-fabric","protobuf","nil-pointer","chaincode-proposal"],"backgroundTag":"proto-marshal-nil-message","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"}