{"record":{"id":"fd16c95eebd851c4","repo":"hyperledger/fabric","slug":"invalid-message-for-creating-lifecycle-chaincode-p","errorCode":null,"errorMessage":"invalid message for creating lifecycle chaincode proposal","messagePattern":"invalid message for creating lifecycle chaincode proposal","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"protoutil/proputils.go","lineNumber":361,"sourceCode":"\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}\n\tcase \"install\":\n\t\tccinp = &peer.ChaincodeInput{Args: [][]byte{[]byte(propType), b}}\n\t}\n\n\t// wrap the deployment in an invocation spec to lscc...\n\tlsccSpec := &peer.ChaincodeInvocationSpec{\n\t\tChaincodeSpec: &peer.ChaincodeSpec{\n\t\t\tType:        peer.ChaincodeSpec_GOLANG,\n\t\t\tChaincodeId: &peer.ChaincodeID{Name: \"lscc\"},\n\t\t\tInput:       ccinp,\n\t\t},\n\t}\n","sourceCodeStart":343,"sourceCodeEnd":379,"githubUrl":"https://github.com/hyperledger/fabric/blob/2736b63f8fd5932511d56fe68b7039d15977f7f6/protoutil/proputils.go#L343-L379","documentation":"createProposalFromCDS builds an install/deploy/upgrade proposal from a ChaincodeDeploymentSpec. For deploy/upgrade proposal types the message argument must be a non-nil *peer.ChaincodeDeploymentSpec; if the type assertion fails or the value is nil, the function refuses to serialize garbage into a proposal and returns this error.","triggerScenarios":"Calling CreateInstallProposalFromCDS, CreateDeployProposalFromCDS, or CreateUpgradeProposalFromCDS with a msg argument that is not a *peer.ChaincodeDeploymentSpec (e.g. a ChaincodeSpec or raw bytes) or is a nil typed pointer.","commonSituations":"Passing a ChaincodeSpec instead of a ChaincodeDeploymentSpec after refactoring; constructing the CDS with &peer.ChaincodeDeploymentSpec{} whose fields were never populated from a CDS parsed elsewhere; nil propagation when upstream spec parsing failed silently.","solutions":["Ensure the message passed is a fully populated *peer.ChaincodeDeploymentSpec (with ChaincodeSpec.ChaincodeId set and CodePackage/GolangProgram populated as needed).","Check that you are calling the right helper: install takes the CDS, deploy/upgrade take (CDS, channelID); don't pass a ChaincodeSpec or ChaincodeInput.","Verify upstream parsing (e.g. utils.UnmarshalCDS / GetChaincodeDeploymentSpec) actually succeeded before building the proposal; handle its error instead of forwarding a nil spec.","If upgrading code from an older fabric release, confirm the proposal-construction helper names and expected message types still match; the lifecycle v2 path uses _lifecycle APIs instead."],"exampleFix":"// before\nprop, _, err := protoutil.CreateDeployProposalFromCDS(chID, spec, signerCert, nil)\n// where spec was a *peer.ChaincodeSpec\n\n// after\ncds, err := utils.GetChaincodeDeploymentSpec(codePackageBytes, true)\nif err != nil {\n    return err\n}\nprop, _, err := protoutil.CreateDeployProposalFromCDS(chID, cds, signerCert, nil)","handlingStrategy":"validation","validationCode":"func validCDS(msg proto.Message) bool {\n    cds, ok := msg.(*peer.ChaincodeDeploymentSpec)\n    return ok && cds != nil && cds.ChaincodeSpec != nil && cds.ChaincodeSpec.ChaincodeId != nil\n}\nif !validCDS(msg) {\n    return errors.New(\"caller must pass a populated *peer.ChaincodeDeploymentSpec\")\n}","typeGuard":"func asCDS(msg interface{}) (*peer.ChaincodeDeploymentSpec, bool) {\n    cds, ok := msg.(*peer.ChaincodeDeploymentSpec)\n    return cds, ok && cds != nil\n}","tryCatchPattern":"prop, txid, err := protoutil.CreateDeployProposalFromCDS(chID, cds, signerCert, nil)\nif err != nil {\n    if err.Error() == \"invalid message for creating lifecycle chaincode proposal\" {\n        return fmt.Errorf(\"bug: non-CDS message passed to deploy proposal builder: %w\", err)\n    }\n    return err\n}","preventionTips":["Always build proposals from a CDS obtained via utils.GetChaincodeDeploymentSpec, never from a ChaincodeSpec.","Nil-check the typed pointer (not just the interface) before calling the proposal builders.","Unit-test each proposal type (install/deploy/upgrade) with the exact message type it expects.","On fabric 2.x prefer the _lifecycle package for install/approve/commit flows."],"tags":["fabric","proposal","chaincode","invalid-argument"],"backgroundTag":"nil-or-wrong-type-proposal-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"}